26-year-old full-stack web/software developer from Würzburg, Germany, with 3-4 years of experience and a strong focus on front end development.
import { NextPage, GetServerSideProps } from 'next'
import Head from 'next/head'
interface Props {
users: { id: number; name: string; email: string }[]
}
const Home: NextPage<Props> = ({ users }) => (
<>
<Head><title>User List</title></Head>
<main className="p-8">
<h1 className="text-2xl font-bold mb-4">Users</h1>
<ul className="space-y-2">
{users.map(u => (
<li key={u.id} className="border p-4 rounded">
<strong>{u.name}</strong> — <a href={`mailto:${u.email}`}>{u.email}</a>
</li>
))}
</ul>
</main>
</>
)
export const getServerSideProps: GetServerSideProps<Props> = async () => {
const res = await fetch('https://jsonplaceholder.typicode.com/users')
const users: Props['users'] = await res.json()
return { props: { users } }
}
export default Home
I use Next.js to build performant, SEO-optimized web apps with seamless full-stack integration—whether generating static pages or handling dynamic data.
import React, { useState, useEffect, ChangeEvent } from 'react';
interface User {
id: number;
name: string;
email: string;
}
export const App: React.FC = () => {
const [users, setUsers] = useState<User[]>([]);
const [filter, setFilter] = useState<string>('');
const [loading, setLoading] = useState<boolean>(true);
const [error, setError] = useState<string | null>(null);
useEffect(() => {
fetch('https://jsonplaceholder.typicode.com/users')
.then(res => {
if (!res.ok) throw new Error(res.statusText);
return res.json() as Promise<User[]>;
})
.then(setUsers)
.catch(err => setError(err.message))
.finally(() => setLoading(false));
}, []);
const filteredUsers = users.filter(u =>
u.name.toLowerCase().includes(filter.toLowerCase())
);
if (loading) return <p>Loading users…</p>;
if (error) return <p>Error: {error}</p>;
return (
<div style={{ padding: '1rem', fontFamily: 'Arial, sans-serif' }}>
<h1>User Directory</h1>
<input
type="text"
placeholder="Search by name"
value={filter}
onChange={(e: ChangeEvent<HTMLInputElement>) => setFilter(e.target.value)}
style={{ marginBottom: '1rem', padding: '0.5rem', width: '100%' }}
/>
<ul style={{ listStyle: 'none', padding: 0 }}>
{filteredUsers.map(user => (
<li key={user.id} style={{ border: '1px solid #ccc', borderRadius: '4px', padding: '0.75rem', marginBottom: '0.5rem' }}>
<h2 style={{ margin: '0 0 0.5rem' }}>{user.name}</h2>
<a href={`mailto:${user.email}`}>{user.email}</a>
</li>
))}
</ul>
</div>
);
};
React forms the core of my frontend toolbox. I build clean, interactive UIs using composable components and best practices for maintainability.
type Grid = boolean[][];
class GameOfLife {
width: number;
height: number;
grid: Grid;
constructor(width: number, height: number) {
this.width = width;
this.height = height;
this.grid = this.makeRandomGrid();
}
// Initialize with random live/dead cells
private makeRandomGrid(): Grid {
const g: Grid = [];
for (let y = 0; y < this.height; y++) {
const row: boolean[] = [];
for (let x = 0; x < this.width; x++) {
row.push(Math.random() < 0.3);
}
g.push(row);
}
return g;
}
// Compute the next generation
step(): void {
const next: Grid = this.grid.map((row, y) =>
row.map((cell, x) => {
const liveNeighbors = this.countLiveNeighbors(x, y);
// Apply Conway's rules
if (cell) {
return liveNeighbors === 2 || liveNeighbors === 3;
} else {
return liveNeighbors === 3;
}
})
);
this.grid = next;
}
private countLiveNeighbors(x: number, y: number): number {
let count = 0;
for (let dy = -1; dy <= 1; dy++) {
for (let dx = -1; dx <= 1; dx++) {
if (dx === 0 && dy === 0) continue;
const nx = (x + dx + this.width) % this.width;
const ny = (y + dy + this.height) % this.height;
if (this.grid[ny][nx]) count++;
}
}
return count;
}
// Render grid to console using ANSI escape codes
render(): void {
process.stdout.write('\x1Bc'); // Clear screen
for (const row of this.grid) {
let line = '';
for (const cell of row) {
line += cell ? '██' : ' ';
}
console.log(line);
}
}
// Run the simulation
run(intervalMs = 100): void {
this.render();
setInterval(() => {
this.step();
this.render();
}, intervalMs);
}
}
// Adjust size as you like
const width = 40;
const height = 20;
const game = new GameOfLife(width, height);
game.run(200);
I use JavaScript and TypeScript daily to write clean, maintainable, and type-safe code across both frontend and backend projects.
#!/usr/bin/env python3
import requests
from bs4 import BeautifulSoup
import json
from collections import Counter
def fetch_top250():
url = 'https://www.imdb.com/chart/top/'
resp = requests.get(url)
resp.raise_for_status()
soup = BeautifulSoup(resp.text, 'html.parser')
rows = soup.select('tbody.lister-list tr')
movies = []
for row in rows:
title_col = row.find('td', class_='titleColumn')
title = title_col.a.text
year = int(title_col.span.text.strip('()'))
rating = float(row.find('td', class_='ratingColumn').strong.text)
# director (first in the "title" attribute, before any commas)
director = title_col.a['title'].split(',')[0]
movies.append({
'title': title,
'year': year,
'rating': rating,
'director': director
})
return movies
def analyze(movies):
# Top 5 directors
dirs = Counter(m['director'] for m in movies).most_common(5)
print("Top 5 directors in IMDb Top 250:")
for name, cnt in dirs:
print(f" {name}: {cnt} film(s)")
# Average rating by decade
by_decade = {}
for m in movies:
decade = (m['year'] // 10) * 10
by_decade.setdefault(decade, []).append(m['rating'])
print("\nAverage rating by decade:")
for dec in sorted(by_decade):
avg = sum(by_decade[dec]) / len(by_decade[dec])
print(f" {dec}s: {avg:.2f}")
def main():
movies = fetch_top250()
# 1) Save to JSON
with open('imdb_top250.json', 'w') as f:
json.dump(movies, f, indent=2)
# 2) Print analyses
analyze(movies)
if __name__ == '__main__':
main()
Python is my go-to for scripts, automation, and backend utilities. I’ve built data processes, APIs, and testing tools to support frontend development and deployment.
<body class="bg-gray-100 text-gray-800">
<!-- Navbar -->
<nav class="bg-white shadow-md">
<div class="max-w-6xl mx-auto px-4">
<div class="flex justify-between items-center h-16">
<a href="#" class="text-2xl font-bold text-indigo-600">Brand</a>
<div class="space-x-4">
<a href="#" class="hover:text-indigo-600">Home</a>
<a href="#" class="hover:text-indigo-600">Features</a>
<a href="#" class="hover:text-indigo-600">Pricing</a>
<a href="#" class="px-4 py-2 bg-indigo-600 text-white rounded hover:bg-indigo-700">Sign In</a>
</div>
</div>
</div>
</nav>
<!-- Hero Section -->
<header class="bg-indigo-600 text-white py-20">
<div class="max-w-4xl mx-auto text-center">
<h1 class="text-4xl font-extrabold mb-4">Build anything with Tailwind CSS</h1>
<p class="mb-8">A utility-first CSS framework packed with classes like flex, pt-4, text-center and rotate-90 that can be composed to build any design, directly in your markup.</p>
<a href="#" class="px-6 py-3 bg-white text-indigo-600 font-semibold rounded hover:bg-gray-100">Get Started</a>
</div>
</header>
<!-- Features Grid -->
<section class="py-16">
<div class="max-w-6xl mx-auto grid gap-6 sm:grid-cols-2 lg:grid-cols-3 px-4">
<div class="bg-white rounded-lg shadow p-6 hover:shadow-lg transition">
<h2 class="text-xl font-semibold mb-2">Responsive Design</h2>
<p>Use responsive prefixes—sm:, md:, lg:—to control how your components look on different screen sizes.</p>
</div>
<div class="bg-white rounded-lg shadow p-6 hover:shadow-lg transition">
<h2 class="text-xl font-semibold mb-2">Dark Mode</h2>
<p>Prefer dark mode? Just add <code>dark:</code> variants and toggle a class on <code><html></code>.</p>
</div>
<div class="bg-white rounded-lg shadow p-6 hover:shadow-lg transition">
<h2 class="text-xl font-semibold mb-2">Customizable</h2>
<p>Configure your design system in <code>tailwind.config.js</code>—colors, spacing, typography, and more.</p>
</div>
</div>
</section>
<!-- Footer -->
<footer class="bg-white border-t py-6">
<div class="max-w-6xl mx-auto text-center text-gray-600">
© 2025 torstendngh. Made with ♥ using Tailwind CSS.
</div>
</footer>
</body>
I leverage Tailwind CSS for rapid prototyping and design consistency, while also writing custom CSS when design nuances require it.
Figma is my go-to tool for UI/UX design. I use it to prototype interfaces, plan layouts, and collaborate across design-development handoff.