1 Commits

Author SHA1 Message Date
Tuan-Dat Tran
77ab7ba702 fix(ci): replace dependabot with renovate for Gitea compatibility
Dependabot only works on GitHub. This repo is hosted on Gitea which
requires Renovate for dependency updates.

- Remove .github/dependabot.yml (unused on Gitea)
- Add renovate.json with recommended config
- Configure npm package updates for / and /backend
- Configure GitHub Actions workflow updates
- Enable automerge for dev dependency minor/patch updates
2026-02-25 06:24:23 +01:00
14 changed files with 156 additions and 480 deletions

View File

@@ -1,32 +0,0 @@
version: 2
updates:
- package-ecosystem: "npm"
directory: "/"
schedule:
interval: "weekly"
day: "monday"
time: "06:00"
open-pull-requests-limit: 5
reviewers:
- "tuan-dat-tran"
labels:
- "dependencies"
commit-message:
prefix: "deps"
include: "scope"
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "weekly"
day: "monday"
time: "06:00"
open-pull-requests-limit: 3
reviewers:
- "tuan-dat-tran"
labels:
- "dependencies"
- "github-actions"
commit-message:
prefix: "ci"
include: "scope"

View File

@@ -1,9 +1,9 @@
FROM node:25-alpine as build
FROM node:20-alpine as build
WORKDIR /app
COPY package*.json ./
RUN npm install --legacy-peer-deps --ignore-scripts
RUN npm ci
COPY . .
RUN npm run build

View File

@@ -1,4 +1,4 @@
FROM node:25-slim
FROM node:20-slim
WORKDIR /app

View File

@@ -24,190 +24,19 @@ export async function initDB() {
await db('cv_data').insert({
id: 1,
data: JSON.stringify({
"personal": {
"name": "Tuan-Dat Tran",
"title": "Junior DevOps Engineer",
"intro": "DevOps Engineer and Homelab Enthusiast based in Essen, Germany. Primary owner of production SaaS platforms on Azure AKS, with a strong background in Linux, automation, and infrastructure engineering.",
"email": "tuan-dat.tran@dextradata.com",
"github": "https://github.com/TuDatTr",
"linkedin": "https://www.linkedin.com/in/tudattr/",
"location": "Essen, Germany"
personal: {
name: "Tuan-Dat Tran",
title: "Junior DevOps Engineer",
intro: "Passionierter DevOps Engineer mit Fokus auf Cloud-Infrastruktur.",
email: "tuan-dat.tran@example.com",
github: "https://github.com/tuan-dat-tran",
linkedin: "https://linkedin.com/in/tuan-dat-tran",
location: "Deutschland"
},
"experience": [
{
"id": 1,
"role": "Junior DevOps Engineer",
"company": "DextraData GRC Technologies GmbH",
"period": "2025 present",
"type": "Full-time",
"description": "Primary owner of the GRASP GRC platform and Logipad aviation SaaS platform, running on Azure AKS and Rancher-managed Kubernetes clusters.",
"highlights": [
"Drives GitOps adoption with ArgoCD across production Kubernetes clusters",
"Manages CI/CD pipelines with Bitbucket Pipelines",
"Leads incident response and on-call for production outages",
"Reduced GRASP frontend pipeline from 30 to 16 minutes",
"Eliminated ~$2k/month Azure logging costs via workspace restructuring",
"Built internal AI tooling with LiteLLM and Ollama",
"Implemented Azure Container Registry mirroring to resolve Docker Hub rate limits"
]
},
{
"id": 2,
"role": "Research Assistant",
"company": "NCS Group, Universität Duisburg-Essen",
"period": "2021 2024",
"type": "Part-time",
"description": "University research group role covering infrastructure management, containerized systems, and networking experiments.",
"highlights": [
"Managed lab infrastructure: Ansible-automated servers, AWS accounts, and inventory systems",
"Built and operated Dockerized and Kubernetes-based experiment environments",
"Co-authored a peer-reviewed publication at IEEE LCN 2023"
]
},
{
"id": 3,
"role": "Student Mentor",
"company": "Universität Duisburg-Essen",
"period": "2021 2022",
"type": "Volunteer",
"description": "Introduced groups of ~20 freshmen to their new academic environment each semester, providing organizational and technical guidance throughout their first year.",
"highlights": [
"Guided new students through academic orientation each semester",
"Provided technical and organizational support throughout the first year"
]
},
{
"id": 4,
"role": "Software Engineer",
"company": "gefeba Engineering GmbH",
"period": "2018 2020",
"type": "Part-time",
"description": "Worked on the company's main product — a frame-based data exchange system for monitoring industrial machinery — and developed a real-time log visualization application.",
"highlights": [
"Developed features for a frame-based industrial data exchange system",
"Built a real-time log visualization application for industrial machinery",
"Stack: C#, Angular, Bootstrap, Entity Framework"
]
},
{
"id": 5,
"role": "Student Council Member",
"company": "Universität Duisburg-Essen",
"period": "2016 2019",
"type": "Volunteer",
"description": "Participated in faculty committees and organized social events. Managed the faculty's IT infrastructure and provided support to fellow students.",
"highlights": [
"Managed faculty IT infrastructure (Linux, Networking, LaTeX)",
"Organized social events and participated in faculty committees",
"Provided subject-specific and organizational support to fellow students"
]
},
{
"id": 6,
"role": "Software Engineer",
"company": "gefeba Engineering GmbH",
"period": "2013 2015",
"type": "Part-time",
"description": "Joined after a school internship. Worked on internal ERP projects, designed a mail traffic management tool, and contributed to master data management tooling.",
"highlights": [
"Developed internal ERP project features",
"Designed a tool for managing project-related mail traffic",
"Contributed to internal master data management tooling",
"Stack: C#, HTML, CSS, JavaScript"
]
}
],
"skills": {
"Container & Orchestration": [
"Kubernetes",
"Docker",
"Helm",
"ArgoCD"
],
"CI/CD": [
"Bitbucket Pipelines",
"Git"
],
"Cloud": [
"Azure",
"Azure AKS",
"Azure App Gateway",
"Azure Entra ID"
],
"Infrastructure as Code": [
"Ansible"
],
"Observability": [
"ELK Stack",
"Checkmk",
"UptimeRobot"
],
"Databases": [
"PostgreSQL",
"MongoDB",
"CouchDB"
],
"Programming": [
"Rust",
"Python",
"Bash"
]
},
"education": [
{
"id": 1,
"degree": "B.Sc. Systems Engineering",
"institution": "Universität Duisburg-Essen",
"period": "2015 present",
"status": "Bachelor thesis ongoing"
}
],
"projects": [
{
"id": 1,
"name": "Ethereum Smart Contract Fuzzer",
"description": "A fuzzer for Ethereum smart contracts built as part of the bachelor thesis project.",
"url": "#",
"tech": [
"Rust"
]
},
{
"id": 2,
"name": "Homelab",
"description": "Ansible-managed homelab running on Debian Linux with Raspberry Pi, Mikrotik networking, Pihole, and self-hosted services.",
"url": "https://git.tudattr.dev/tudattr/ansible",
"tech": [
"Ansible",
"Kubernetes",
"Debian Linux"
]
},
{
"id": 3,
"name": ".dotfiles",
"description": "Configuration files for daily-use tools providing a reproducible baseline for any personal ArchLinux system, including NeoVim (LazyVim), Zellij, and k9s.",
"url": "https://github.com/TuDatTr/dotfiles",
"tech": [
"Zsh",
"NeoVim",
"Zellij",
"ArchLinux"
]
},
{
"id": 4,
"name": "tudattr.dev",
"description": "Full-stack WebAssembly personal website built with the Rust-based Dioxus framework and Tailwind CSS.",
"url": "https://www.tudattr.dev",
"tech": [
"Rust",
"Dioxus",
"Tailwind CSS",
"WebAssembly"
]
}
]
experience: [],
skills: {},
education: [],
projects: []
})
});
console.log('Initialized database with default CV data');

View File

@@ -9,9 +9,9 @@
"test:watch": "vitest"
},
"dependencies": {
"better-sqlite3": "^12.0.0",
"better-sqlite3": "^11.7.0",
"cors": "^2.8.5",
"express": "^5.0.0",
"express": "^4.21.2",
"knex": "^3.1.0",
"swagger-jsdoc": "^6.2.8",
"swagger-ui-express": "^5.0.1"

View File

@@ -4,7 +4,6 @@
"version": "1.1.0",
"type": "module",
"scripts": {
"sync-profile": "node scripts/sync-profile.mjs",
"dev": "vite",
"build": "vite build",
"lint": "eslint .",
@@ -33,7 +32,7 @@
],
"dependencies": {
"framer-motion": "^12.34.1",
"lucide-react": "^0.577.0",
"lucide-react": "^0.574.0",
"react": "^19.2.0",
"react-dom": "^19.2.0",
"react-router-dom": "^7.13.0"
@@ -41,7 +40,7 @@
"devDependencies": {
"@commitlint/cli": "^20.4.2",
"@commitlint/config-conventional": "^20.4.2",
"@eslint/js": "^10.0.0",
"@eslint/js": "^9.39.1",
"@lhci/cli": "^0.15.1",
"@playwright/test": "^1.58.2",
"@semantic-release/changelog": "^6.0.3",
@@ -52,24 +51,24 @@
"@testing-library/react": "^16.3.2",
"@types/react": "^19.2.7",
"@types/react-dom": "^19.2.3",
"@vitejs/plugin-react": "^6.0.0",
"@vitejs/plugin-react": "^5.1.1",
"@vitest/coverage-v8": "^4.0.18",
"autoprefixer": "^10.4.24",
"better-sqlite3": "^12.6.2",
"bundlesize": "^0.18.2",
"cors": "^2.8.6",
"eslint": "^10.0.0",
"eslint": "^9.39.1",
"eslint-plugin-react-hooks": "^7.0.1",
"eslint-plugin-react-refresh": "^0.5.0",
"eslint-plugin-react-refresh": "^0.4.24",
"express": "^5.2.1",
"globals": "^17.0.0",
"globals": "^16.5.0",
"husky": "^9.1.7",
"jsdom": "^28.1.0",
"postcss": "^8.5.6",
"semantic-release": "^25.0.3",
"supertest": "^7.2.2",
"tailwindcss": "^4.1.18",
"vite": "^8.0.0",
"vite": "^7.3.1",
"vitest": "^4.0.18"
}
}

View File

@@ -1,3 +1,37 @@
{
"$schema": "https://docs.renovatebot.com/renovate-schema.json"
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
"extends": [
"config:recommended"
],
"timezone": "Europe/Berlin",
"schedule": ["on monday before 10:00am"],
"prConcurrentLimit": 5,
"prHourlyLimit": 2,
"labels": ["dependencies"],
"commitMessagePrefix": "deps",
"commitMessageAction": "update",
"packageRules": [
{
"matchManagers": ["npm"],
"rangeStrategy": "bump",
"semanticCommitType": "deps",
"semanticCommitScope": "{{packageFileDir}}"
},
{
"matchManagers": ["github-actions"],
"semanticCommitType": "ci",
"semanticCommitScope": "actions",
"groupName": "github-actions"
},
{
"matchDepTypes": ["devDependencies"],
"matchUpdateTypes": ["minor", "patch"],
"automerge": true
}
],
"lockFileMaintenance": {
"enabled": true,
"schedule": ["on the first day of the month"]
},
"postUpdateOptions": ["npmDedupe"]
}

View File

@@ -1,60 +0,0 @@
#!/usr/bin/env node
/**
* Reads cv-data.json from the persons profile directory and writes it into:
* - src/lib/cv.json (frontend default / compile-time fallback)
* - backend/db/init.js (backend DB seed on first boot)
*
* Usage:
* node scripts/sync-profile.mjs [path/to/cv-data.json]
*
* Default source path: ~/workspace/persons/tuan-dat.tran/cv-data.json
*/
import { readFileSync, writeFileSync } from 'fs';
import { resolve } from 'path';
import { homedir } from 'os';
import { fileURLToPath } from 'url';
import { dirname } from 'path';
const __dirname = dirname(fileURLToPath(import.meta.url));
const root = resolve(__dirname, '..');
const sourcePath = process.argv[2]
?? resolve(homedir(), 'workspace/persons/tuan-dat.tran/cv-data.json');
let data;
try {
data = JSON.parse(readFileSync(sourcePath, 'utf8'));
} catch (e) {
console.error(`Failed to read ${sourcePath}: ${e.message}`);
process.exit(1);
}
// 1. Write src/lib/cv.json
const cvJsonPath = resolve(root, 'src/lib/cv.json');
writeFileSync(cvJsonPath, JSON.stringify(data, null, 2) + '\n');
console.log(`wrote ${cvJsonPath}`);
// 2. Rewrite the seed block in backend/db/init.js
const initPath = resolve(root, 'backend/db/init.js');
const initSrc = readFileSync(initPath, 'utf8');
const seedJson = JSON.stringify(data, null, 8)
.split('\n')
.map((line, i) => i === 0 ? line : ' ' + line)
.join('\n');
const updated = initSrc.replace(
/data: JSON\.stringify\([\s\S]*?\)\s*\}\);/,
`data: JSON.stringify(${seedJson})\n });`
);
if (updated === initSrc) {
console.error('Could not find seed block in backend/db/init.js — pattern mismatch');
process.exit(1);
}
writeFileSync(initPath, updated);
console.log(`wrote ${initPath}`);
console.log('done — rebuild Docker images and restart with a fresh volume to apply');

View File

@@ -7,20 +7,25 @@ export default function Education() {
const { education } = data;
return (
<section id="education" className="py-12 px-6">
<section id="education" className="py-20 px-6">
<div className="max-w-4xl mx-auto">
<motion.h2
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
whileInView={{ opacity: 1 }}
viewport={{ once: true }}
className="text-3xl font-bold text-slate-900 mb-12 text-center"
>
Education
Ausbildung
</motion.h2>
<div className="grid md:grid-cols-2 gap-6">
{education.map((edu, index) => (
<div
<motion.div
key={edu.id}
initial={{ opacity: 0, y: 20 }}
whileInView={{ opacity: 1, y: 0 }}
viewport={{ once: true }}
transition={{ delay: index * 0.2 }}
className="bg-white rounded-xl p-6 shadow-sm border border-slate-100"
>
<div className="flex items-start gap-4">
@@ -39,7 +44,7 @@ export default function Education() {
</span>
</div>
</div>
</div>
</motion.div>
))}
</div>
</div>

View File

@@ -7,20 +7,25 @@ export default function Experience() {
const { experience } = data;
return (
<section id="experience" className="py-12 px-6">
<section id="experience" className="py-20 px-6">
<div className="max-w-4xl mx-auto">
<motion.h2
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
whileInView={{ opacity: 1 }}
viewport={{ once: true }}
className="text-3xl font-bold text-slate-900 mb-12 text-center"
>
Experience
Berufserfahrung
</motion.h2>
<div className="relative">
{experience.map((exp, index) => (
<div
<motion.div
key={exp.id}
initial={{ opacity: 0, x: -20 }}
whileInView={{ opacity: 1, x: 0 }}
viewport={{ once: true }}
transition={{ delay: index * 0.2 }}
className="relative pl-8 pb-12 last:pb-0"
>
<div className="absolute left-0 top-2 w-4 h-4 rounded-full bg-primary-500 border-4 border-primary-100" />
@@ -58,7 +63,7 @@ export default function Experience() {
))}
</ul>
</div>
</div>
</motion.div>
))}
</div>
</div>

View File

@@ -7,7 +7,7 @@ export default function Hero() {
const { personal } = data;
return (
<section className="flex items-center justify-center px-6 py-16">
<section className="min-h-screen flex items-center justify-center px-6 py-20">
<motion.div
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}

View File

@@ -7,14 +7,15 @@ export default function Projects() {
const { projects } = data;
return (
<section id="projects" className="py-12 px-6 bg-white">
<section id="projects" className="py-20 px-6 bg-white">
<div className="max-w-4xl mx-auto">
<motion.h2
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
whileInView={{ opacity: 1 }}
viewport={{ once: true }}
className="text-3xl font-bold text-slate-900 mb-12 text-center"
>
Projects
Projekte
</motion.h2>
<div className="grid md:grid-cols-2 gap-6">
@@ -24,6 +25,10 @@ export default function Projects() {
href={project.url}
target="_blank"
rel="noopener noreferrer"
initial={{ opacity: 0, y: 20 }}
whileInView={{ opacity: 1, y: 0 }}
viewport={{ once: true }}
transition={{ delay: index * 0.2 }}
whileHover={{ y: -4 }}
className="group bg-slate-50 rounded-xl p-6 border border-slate-100 hover:border-primary-200 hover:shadow-md transition-all"
>

View File

@@ -5,22 +5,17 @@ const skillIcons = {
"Docker": "🐳",
"Kubernetes": "☸️",
"Helm": "⛵",
"ArgoCD": "🔄",
"Jenkins": "🔧",
"Bitbucket Pipelines": "📘",
"Bitbucket": "📘",
"ArgoCD": "🔄",
"Git": "📝",
"Azure": "☁️",
"Azure AKS": "",
"Ansible": "⚙️",
"ELK Stack": "📊",
"PostgreSQL": "🐘",
"MongoDB": "🍃",
"Rust": "🦀",
"Azure Resource Manager": "🏗",
"Release Engineering": "🚀",
"Linux Administration": "🐧",
"Python": "🐍",
"Bash": "💻",
"P4": "🔬",
"Intel Tofino": "🔬",
"Linux Administration": "🐧",
"Rust": "🦀"
};
export default function Skills() {
@@ -28,11 +23,12 @@ export default function Skills() {
const { skills } = data;
return (
<section id="skills" className="py-12 px-6 bg-white">
<section id="skills" className="py-20 px-6 bg-white">
<div className="max-w-4xl mx-auto">
<motion.h2
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
whileInView={{ opacity: 1 }}
viewport={{ once: true }}
className="text-3xl font-bold text-slate-900 mb-12 text-center"
>
Skills
@@ -40,8 +36,12 @@ export default function Skills() {
<div className="grid md:grid-cols-2 gap-8">
{Object.entries(skills).map(([category, items], catIndex) => (
<div
<motion.div
key={category}
initial={{ opacity: 0, y: 20 }}
whileInView={{ opacity: 1, y: 0 }}
viewport={{ once: true }}
transition={{ delay: catIndex * 0.1 }}
className="bg-slate-50 rounded-xl p-6"
>
<h3 className="text-lg font-semibold text-primary-600 mb-4">
@@ -51,6 +51,10 @@ export default function Skills() {
{items.map((skill, i) => (
<motion.span
key={skill}
initial={{ opacity: 0, scale: 0.8 }}
whileInView={{ opacity: 1, scale: 1 }}
viewport={{ once: true }}
transition={{ delay: i * 0.05 }}
whileHover={{ scale: 1.05 }}
className="px-3 py-1.5 bg-white rounded-lg text-sm text-slate-700 shadow-sm border border-slate-100 flex items-center gap-1.5 cursor-default"
>
@@ -59,7 +63,7 @@ export default function Skills() {
</motion.span>
))}
</div>
</div>
</motion.div>
))}
</div>
</div>

View File

@@ -2,185 +2,72 @@
"personal": {
"name": "Tuan-Dat Tran",
"title": "Junior DevOps Engineer",
"intro": "DevOps Engineer and Homelab Enthusiast based in Essen, Germany. Primary owner of production SaaS platforms on Azure AKS, with a strong background in Linux, automation, and infrastructure engineering.",
"email": "tuan-dat.tran@dextradata.com",
"github": "https://github.com/TuDatTr",
"linkedin": "https://www.linkedin.com/in/tudattr/",
"location": "Essen, Germany"
"intro": "Passionierter DevOps Engineer mit Fokus auf Cloud-Infrastruktur, Container-Orchestrierung und automatisierte Deployment-Pipelines.",
"email": "tuan-dat.tran@example.com",
"github": "https://github.com/tuan-dat-tran",
"linkedin": "https://linkedin.com/in/tuan-dat-tran",
"location": "Deutschland"
},
"experience": [
{
"id": 1,
"role": "Junior DevOps Engineer",
"company": "DextraData GRC Technologies GmbH",
"period": "2025 present",
"type": "Full-time",
"description": "Primary owner of the GRASP GRC platform and Logipad aviation SaaS platform, running on Azure AKS and Rancher-managed Kubernetes clusters.",
"company": "Unternehmen",
"period": "Seit 2025",
"type": "Vollzeit",
"description": "Verantwortlich für CI/CD Pipelines, Container-Orchestrierung und Cloud-Infrastruktur auf Azure.",
"highlights": [
"Drives GitOps adoption with ArgoCD across production Kubernetes clusters",
"Manages CI/CD pipelines with Bitbucket Pipelines",
"Leads incident response and on-call for production outages",
"Reduced GRASP frontend pipeline from 30 to 16 minutes",
"Eliminated ~$2k/month Azure logging costs via workspace restructuring",
"Built internal AI tooling with LiteLLM and Ollama",
"Implemented Azure Container Registry mirroring to resolve Docker Hub rate limits"
"Automatisierte Deployments mit Jenkins und Bitbucket Pipelines",
"Kubernetes Cluster Management mit Helm und ArgoCD",
"Infrastructure as Code mit Azure Resource Manager"
]
},
{
"id": 2,
"role": "Research Assistant",
"company": "NCS Group, Universität Duisburg-Essen",
"period": "2021 2024",
"type": "Part-time",
"description": "University research group role covering infrastructure management, containerized systems, and networking experiments.",
"role": "Software Entwickler",
"company": "Verschiedene Unternehmen",
"period": "2021 - 2025",
"type": "Teilzeit / Werkstudent / SHK",
"description": "Entwicklung und Maintenance von Softwarelösungen in verschiedenen Rollen.",
"highlights": [
"Managed lab infrastructure: Ansible-automated servers, AWS accounts, and inventory systems",
"Built and operated Dockerized and Kubernetes-based experiment environments",
"Co-authored a peer-reviewed publication at IEEE LCN 2023"
]
},
{
"id": 3,
"role": "Student Mentor",
"company": "Universität Duisburg-Essen",
"period": "2021 2022",
"type": "Volunteer",
"description": "Introduced groups of ~20 freshmen to their new academic environment each semester, providing organizational and technical guidance throughout their first year.",
"highlights": [
"Guided new students through academic orientation each semester",
"Provided technical and organizational support throughout the first year"
]
},
{
"id": 4,
"role": "Software Engineer",
"company": "gefeba Engineering GmbH",
"period": "2018 2020",
"type": "Part-time",
"description": "Worked on the company's main product — a frame-based data exchange system for monitoring industrial machinery — and developed a real-time log visualization application.",
"highlights": [
"Developed features for a frame-based industrial data exchange system",
"Built a real-time log visualization application for industrial machinery",
"Stack: C#, Angular, Bootstrap, Entity Framework"
]
},
{
"id": 5,
"role": "Student Council Member",
"company": "Universität Duisburg-Essen",
"period": "2016 2019",
"type": "Volunteer",
"description": "Participated in faculty committees and organized social events. Managed the faculty's IT infrastructure and provided support to fellow students.",
"highlights": [
"Managed faculty IT infrastructure (Linux, Networking, LaTeX)",
"Organized social events and participated in faculty committees",
"Provided subject-specific and organizational support to fellow students"
]
},
{
"id": 6,
"role": "Software Engineer",
"company": "gefeba Engineering GmbH",
"period": "2013 2015",
"type": "Part-time",
"description": "Joined after a school internship. Worked on internal ERP projects, designed a mail traffic management tool, and contributed to master data management tooling.",
"highlights": [
"Developed internal ERP project features",
"Designed a tool for managing project-related mail traffic",
"Contributed to internal master data management tooling",
"Stack: C#, HTML, CSS, JavaScript"
"Backend-Entwicklung mit Python",
"Linux System Administration",
"Git Version Control und Release Engineering"
]
}
],
"skills": {
"Container & Orchestration": [
"Kubernetes",
"Docker",
"Helm",
"ArgoCD"
],
"CI/CD": [
"Bitbucket Pipelines",
"Git"
],
"Cloud": [
"Azure",
"Azure AKS",
"Azure App Gateway",
"Azure Entra ID"
],
"Infrastructure as Code": [
"Ansible"
],
"Observability": [
"ELK Stack",
"Checkmk",
"UptimeRobot"
],
"Databases": [
"PostgreSQL",
"MongoDB",
"CouchDB"
],
"Programming": [
"Rust",
"Python",
"Bash"
]
"Container & Orchestration": ["Docker", "Kubernetes", "Helm"],
"CI/CD & GitOps": ["Jenkins", "Bitbucket", "ArgoCD", "Git"],
"Cloud": ["Azure"],
"Infrastructure as Code": ["Azure Resource Manager"],
"Release Engineering": ["Release Engineering"],
"Operating Systems": ["Linux Administration"],
"Programming": ["Python", "Bash", "Rust"]
},
"education": [
{
"id": 1,
"degree": "B.Sc. Systems Engineering",
"institution": "Universität Duisburg-Essen",
"period": "2015 present",
"status": "Bachelor thesis ongoing"
"degree": "Bachelor Informatik",
"institution": "Universität",
"period": "Laufend",
"status": "Bachelorarbeit offen"
}
],
"projects": [
{
"id": 1,
"name": "Ethereum Smart Contract Fuzzer",
"description": "A fuzzer for Ethereum smart contracts built as part of the bachelor thesis project.",
"name": "Projekt 1",
"description": "Beschreibung folgt",
"url": "#",
"tech": [
"Rust"
]
"tech": ["Docker", "Kubernetes", "ArgoCD"]
},
{
"id": 2,
"name": "Homelab",
"description": "Ansible-managed homelab running on Debian Linux with Raspberry Pi, Mikrotik networking, Pihole, and self-hosted services.",
"url": "https://git.tudattr.dev/tudattr/ansible",
"tech": [
"Ansible",
"Kubernetes",
"Debian Linux"
]
},
{
"id": 3,
"name": ".dotfiles",
"description": "Configuration files for daily-use tools providing a reproducible baseline for any personal ArchLinux system, including NeoVim (LazyVim), Zellij, and k9s.",
"url": "https://github.com/TuDatTr/dotfiles",
"tech": [
"Zsh",
"NeoVim",
"Zellij",
"ArchLinux"
]
},
{
"id": 4,
"name": "tudattr.dev",
"description": "Full-stack WebAssembly personal website built with the Rust-based Dioxus framework and Tailwind CSS.",
"url": "https://www.tudattr.dev",
"tech": [
"Rust",
"Dioxus",
"Tailwind CSS",
"WebAssembly"
]
"name": "Projekt 2",
"description": "Beschreibung folgt",
"url": "#",
"tech": ["Azure", "ARM", "Jenkins"]
}
]
}