auto-claude: subtask-5-1 - Create ChatMessage component for individual messages
Created ChatMessage.tsx component with: - ChatMessage component for displaying user/assistant messages - Styled differently based on role (user right-aligned, assistant left-aligned) - Framer Motion animations for smooth appearance - Streaming indicator for real-time response display - TypingIndicator component for loading state - WelcomeMessage component for empty chat state - Timestamp formatting utility - Responsive design following existing Tailwind patterns Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,227 @@
|
||||
{
|
||||
"base_commands": [
|
||||
".",
|
||||
"[",
|
||||
"[[",
|
||||
"ag",
|
||||
"awk",
|
||||
"basename",
|
||||
"bash",
|
||||
"bc",
|
||||
"break",
|
||||
"cat",
|
||||
"cd",
|
||||
"chmod",
|
||||
"clear",
|
||||
"cmp",
|
||||
"column",
|
||||
"comm",
|
||||
"command",
|
||||
"continue",
|
||||
"cp",
|
||||
"curl",
|
||||
"cut",
|
||||
"date",
|
||||
"df",
|
||||
"diff",
|
||||
"dig",
|
||||
"dirname",
|
||||
"du",
|
||||
"echo",
|
||||
"egrep",
|
||||
"env",
|
||||
"eval",
|
||||
"exec",
|
||||
"exit",
|
||||
"expand",
|
||||
"export",
|
||||
"expr",
|
||||
"false",
|
||||
"fd",
|
||||
"fgrep",
|
||||
"file",
|
||||
"find",
|
||||
"fmt",
|
||||
"fold",
|
||||
"gawk",
|
||||
"gh",
|
||||
"git",
|
||||
"grep",
|
||||
"gunzip",
|
||||
"gzip",
|
||||
"head",
|
||||
"help",
|
||||
"host",
|
||||
"iconv",
|
||||
"id",
|
||||
"jobs",
|
||||
"join",
|
||||
"jq",
|
||||
"kill",
|
||||
"killall",
|
||||
"less",
|
||||
"let",
|
||||
"ln",
|
||||
"ls",
|
||||
"lsof",
|
||||
"man",
|
||||
"mkdir",
|
||||
"mktemp",
|
||||
"more",
|
||||
"mv",
|
||||
"nl",
|
||||
"paste",
|
||||
"pgrep",
|
||||
"ping",
|
||||
"pkill",
|
||||
"popd",
|
||||
"printenv",
|
||||
"printf",
|
||||
"ps",
|
||||
"pushd",
|
||||
"pwd",
|
||||
"read",
|
||||
"readlink",
|
||||
"realpath",
|
||||
"reset",
|
||||
"return",
|
||||
"rev",
|
||||
"rg",
|
||||
"rm",
|
||||
"rmdir",
|
||||
"sed",
|
||||
"seq",
|
||||
"set",
|
||||
"sh",
|
||||
"shuf",
|
||||
"sleep",
|
||||
"sort",
|
||||
"source",
|
||||
"split",
|
||||
"stat",
|
||||
"tail",
|
||||
"tar",
|
||||
"tee",
|
||||
"test",
|
||||
"time",
|
||||
"timeout",
|
||||
"touch",
|
||||
"tr",
|
||||
"tree",
|
||||
"true",
|
||||
"type",
|
||||
"uname",
|
||||
"unexpand",
|
||||
"uniq",
|
||||
"unset",
|
||||
"unzip",
|
||||
"watch",
|
||||
"wc",
|
||||
"wget",
|
||||
"whereis",
|
||||
"which",
|
||||
"whoami",
|
||||
"xargs",
|
||||
"yes",
|
||||
"yq",
|
||||
"zip",
|
||||
"zsh"
|
||||
],
|
||||
"stack_commands": [
|
||||
"ar",
|
||||
"clang",
|
||||
"clang++",
|
||||
"cmake",
|
||||
"composer",
|
||||
"dive",
|
||||
"docker",
|
||||
"docker-buildx",
|
||||
"docker-compose",
|
||||
"dockerfile",
|
||||
"eslint",
|
||||
"g++",
|
||||
"gcc",
|
||||
"ipython",
|
||||
"jupyter",
|
||||
"ld",
|
||||
"make",
|
||||
"meson",
|
||||
"next",
|
||||
"ninja",
|
||||
"nm",
|
||||
"node",
|
||||
"notebook",
|
||||
"npm",
|
||||
"npx",
|
||||
"objdump",
|
||||
"pdb",
|
||||
"php",
|
||||
"pip",
|
||||
"pip3",
|
||||
"pipx",
|
||||
"pnpm",
|
||||
"pnpx",
|
||||
"pudb",
|
||||
"python",
|
||||
"python3",
|
||||
"react-scripts",
|
||||
"strip",
|
||||
"ts-node",
|
||||
"tsc",
|
||||
"tsx",
|
||||
"vitest"
|
||||
],
|
||||
"script_commands": [
|
||||
"bun",
|
||||
"npm",
|
||||
"pnpm",
|
||||
"yarn"
|
||||
],
|
||||
"custom_commands": [],
|
||||
"detected_stack": {
|
||||
"languages": [
|
||||
"python",
|
||||
"javascript",
|
||||
"typescript",
|
||||
"php",
|
||||
"c"
|
||||
],
|
||||
"package_managers": [
|
||||
"pnpm"
|
||||
],
|
||||
"frameworks": [
|
||||
"nextjs",
|
||||
"react",
|
||||
"vitest",
|
||||
"eslint"
|
||||
],
|
||||
"databases": [],
|
||||
"infrastructure": [
|
||||
"docker"
|
||||
],
|
||||
"cloud_providers": [],
|
||||
"code_quality_tools": [],
|
||||
"version_managers": []
|
||||
},
|
||||
"custom_scripts": {
|
||||
"npm_scripts": [
|
||||
"dev",
|
||||
"build",
|
||||
"start",
|
||||
"lint",
|
||||
"build:images",
|
||||
"generate:images",
|
||||
"generate:images:dry",
|
||||
"test",
|
||||
"test:coverage"
|
||||
],
|
||||
"make_targets": [],
|
||||
"poetry_scripts": [],
|
||||
"cargo_aliases": [],
|
||||
"shell_scripts": []
|
||||
},
|
||||
"project_dir": "C:\\Users\\damja\\WebstormProjects\\Portfolio",
|
||||
"created_at": "2026-01-22T15:28:38.237190",
|
||||
"project_hash": "c4ad399e16be367eb4e6b076fe1d9ee3",
|
||||
"inherited_from": "C:\\Users\\damja\\WebstormProjects\\Portfolio"
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
{
|
||||
"active": true,
|
||||
"spec": "002-recherchiere-weitere-seo-optimierungen-an-der-webs",
|
||||
"state": "building",
|
||||
"subtasks": {
|
||||
"completed": 15,
|
||||
"total": 27,
|
||||
"in_progress": 1,
|
||||
"failed": 0
|
||||
},
|
||||
"phase": {
|
||||
"current": "Chatbot Frontend",
|
||||
"id": null,
|
||||
"total": 3
|
||||
},
|
||||
"workers": {
|
||||
"active": 0,
|
||||
"max": 1
|
||||
},
|
||||
"session": {
|
||||
"number": 15,
|
||||
"started_at": "2026-01-25T00:03:26.706142"
|
||||
},
|
||||
"last_update": "2026-01-25T00:57:00.939315"
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
{
|
||||
"sandbox": {
|
||||
"enabled": true,
|
||||
"autoAllowBashIfSandboxed": true
|
||||
},
|
||||
"permissions": {
|
||||
"defaultMode": "acceptEdits",
|
||||
"allow": [
|
||||
"Read(./**)",
|
||||
"Write(./**)",
|
||||
"Edit(./**)",
|
||||
"Glob(./**)",
|
||||
"Grep(./**)",
|
||||
"Read(C:\\Users\\damja\\WebstormProjects\\Portfolio\\.auto-claude\\worktrees\\tasks\\002-recherchiere-weitere-seo-optimierungen-an-der-webs/**)",
|
||||
"Write(C:\\Users\\damja\\WebstormProjects\\Portfolio\\.auto-claude\\worktrees\\tasks\\002-recherchiere-weitere-seo-optimierungen-an-der-webs/**)",
|
||||
"Edit(C:\\Users\\damja\\WebstormProjects\\Portfolio\\.auto-claude\\worktrees\\tasks\\002-recherchiere-weitere-seo-optimierungen-an-der-webs/**)",
|
||||
"Glob(C:\\Users\\damja\\WebstormProjects\\Portfolio\\.auto-claude\\worktrees\\tasks\\002-recherchiere-weitere-seo-optimierungen-an-der-webs/**)",
|
||||
"Grep(C:\\Users\\damja\\WebstormProjects\\Portfolio\\.auto-claude\\worktrees\\tasks\\002-recherchiere-weitere-seo-optimierungen-an-der-webs/**)",
|
||||
"Read(C:\\Users\\damja\\WebstormProjects\\Portfolio\\.auto-claude\\worktrees\\tasks\\002-recherchiere-weitere-seo-optimierungen-an-der-webs\\.auto-claude\\specs\\002-recherchiere-weitere-seo-optimierungen-an-der-webs/**)",
|
||||
"Write(C:\\Users\\damja\\WebstormProjects\\Portfolio\\.auto-claude\\worktrees\\tasks\\002-recherchiere-weitere-seo-optimierungen-an-der-webs\\.auto-claude\\specs\\002-recherchiere-weitere-seo-optimierungen-an-der-webs/**)",
|
||||
"Edit(C:\\Users\\damja\\WebstormProjects\\Portfolio\\.auto-claude\\worktrees\\tasks\\002-recherchiere-weitere-seo-optimierungen-an-der-webs\\.auto-claude\\specs\\002-recherchiere-weitere-seo-optimierungen-an-der-webs/**)",
|
||||
"Read(C:\\Users\\damja\\WebstormProjects\\Portfolio\\.auto-claude/**)",
|
||||
"Write(C:\\Users\\damja\\WebstormProjects\\Portfolio\\.auto-claude/**)",
|
||||
"Edit(C:\\Users\\damja\\WebstormProjects\\Portfolio\\.auto-claude/**)",
|
||||
"Glob(C:\\Users\\damja\\WebstormProjects\\Portfolio\\.auto-claude/**)",
|
||||
"Grep(C:\\Users\\damja\\WebstormProjects\\Portfolio\\.auto-claude/**)",
|
||||
"Bash(*)",
|
||||
"WebFetch(*)",
|
||||
"WebSearch(*)",
|
||||
"mcp__context7__resolve-library-id(*)",
|
||||
"mcp__context7__get-library-docs(*)",
|
||||
"mcp__graphiti-memory__search_nodes(*)",
|
||||
"mcp__graphiti-memory__search_facts(*)",
|
||||
"mcp__graphiti-memory__add_episode(*)",
|
||||
"mcp__graphiti-memory__get_episodes(*)",
|
||||
"mcp__graphiti-memory__get_entity_edge(*)"
|
||||
]
|
||||
}
|
||||
}
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,171 @@
|
||||
'use client';
|
||||
|
||||
import { motion } from 'framer-motion';
|
||||
import { User, Bot } from 'lucide-react';
|
||||
|
||||
export type ChatRole = 'user' | 'assistant' | 'system';
|
||||
|
||||
export interface ChatMessageData {
|
||||
id?: string;
|
||||
role: ChatRole;
|
||||
content: string;
|
||||
created_at?: string;
|
||||
isStreaming?: boolean;
|
||||
}
|
||||
|
||||
interface ChatMessageProps {
|
||||
message: ChatMessageData;
|
||||
index?: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats a timestamp for display
|
||||
*/
|
||||
function formatTime(timestamp?: string): string {
|
||||
if (!timestamp) return '';
|
||||
|
||||
try {
|
||||
const date = new Date(timestamp);
|
||||
return date.toLocaleTimeString(undefined, {
|
||||
hour: '2-digit',
|
||||
minute: '2-digit',
|
||||
});
|
||||
} catch {
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* ChatMessage component for displaying individual chat messages
|
||||
* Styled differently based on message role (user vs assistant)
|
||||
*/
|
||||
export function ChatMessage({ message, index = 0 }: ChatMessageProps) {
|
||||
const { role, content, created_at, isStreaming } = message;
|
||||
|
||||
// Don't render system messages
|
||||
if (role === 'system') {
|
||||
return null;
|
||||
}
|
||||
|
||||
const isUser = role === 'user';
|
||||
const formattedTime = formatTime(created_at);
|
||||
|
||||
return (
|
||||
<motion.div
|
||||
initial={{ opacity: 0, y: 10 }}
|
||||
animate={{ opacity: 1, y: 0 }}
|
||||
transition={{ delay: index * 0.05, duration: 0.2 }}
|
||||
className={`flex gap-3 ${isUser ? 'flex-row-reverse' : 'flex-row'}`}
|
||||
>
|
||||
{/* Avatar */}
|
||||
<div
|
||||
className={`flex-shrink-0 w-8 h-8 rounded-full flex items-center justify-center ${
|
||||
isUser
|
||||
? 'bg-zinc-600/50'
|
||||
: 'bg-zinc-800/50 border border-zinc-700'
|
||||
}`}
|
||||
>
|
||||
{isUser ? (
|
||||
<User className="w-4 h-4 text-zinc-300" />
|
||||
) : (
|
||||
<Bot className="w-4 h-4 text-zinc-400" />
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* Message Content */}
|
||||
<div
|
||||
className={`flex flex-col max-w-[80%] ${
|
||||
isUser ? 'items-end' : 'items-start'
|
||||
}`}
|
||||
>
|
||||
<div
|
||||
className={`px-4 py-3 rounded-2xl ${
|
||||
isUser
|
||||
? 'bg-zinc-600/50 text-white rounded-tr-sm'
|
||||
: 'bg-zinc-800/50 border border-zinc-800 text-zinc-200 rounded-tl-sm'
|
||||
}`}
|
||||
>
|
||||
<p className="text-sm whitespace-pre-wrap break-words leading-relaxed">
|
||||
{content}
|
||||
{isStreaming && (
|
||||
<span className="inline-block w-1.5 h-4 ml-1 bg-zinc-400 animate-pulse rounded-sm" />
|
||||
)}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{/* Timestamp */}
|
||||
{formattedTime && !isStreaming && (
|
||||
<span className="text-xs text-zinc-500 mt-1 px-1">
|
||||
{formattedTime}
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
</motion.div>
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Typing indicator shown when assistant is generating a response
|
||||
*/
|
||||
export function TypingIndicator() {
|
||||
return (
|
||||
<motion.div
|
||||
initial={{ opacity: 0, y: 10 }}
|
||||
animate={{ opacity: 1, y: 0 }}
|
||||
exit={{ opacity: 0, y: -10 }}
|
||||
className="flex gap-3"
|
||||
>
|
||||
{/* Avatar */}
|
||||
<div className="flex-shrink-0 w-8 h-8 rounded-full flex items-center justify-center bg-zinc-800/50 border border-zinc-700">
|
||||
<Bot className="w-4 h-4 text-zinc-400" />
|
||||
</div>
|
||||
|
||||
{/* Typing dots */}
|
||||
<div className="px-4 py-3 rounded-2xl rounded-tl-sm bg-zinc-800/50 border border-zinc-800">
|
||||
<div className="flex gap-1.5">
|
||||
{[0, 1, 2].map((i) => (
|
||||
<motion.span
|
||||
key={i}
|
||||
className="w-2 h-2 bg-zinc-500 rounded-full"
|
||||
animate={{
|
||||
opacity: [0.4, 1, 0.4],
|
||||
scale: [0.8, 1, 0.8],
|
||||
}}
|
||||
transition={{
|
||||
duration: 1,
|
||||
repeat: Infinity,
|
||||
delay: i * 0.2,
|
||||
}}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</motion.div>
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Welcome message component for empty chat state
|
||||
*/
|
||||
export function WelcomeMessage() {
|
||||
return (
|
||||
<motion.div
|
||||
initial={{ opacity: 0, y: 20 }}
|
||||
animate={{ opacity: 1, y: 0 }}
|
||||
className="flex flex-col items-center justify-center py-8 px-4 text-center"
|
||||
>
|
||||
<div className="w-12 h-12 rounded-full bg-zinc-800/50 border border-zinc-700 flex items-center justify-center mb-4">
|
||||
<Bot className="w-6 h-6 text-zinc-400" />
|
||||
</div>
|
||||
<h3 className="text-lg font-medium text-white mb-2">
|
||||
Hi, I'm Damjan's AI Assistant
|
||||
</h3>
|
||||
<p className="text-sm text-zinc-400 max-w-xs">
|
||||
I can help you learn about Damjan's skills, services, and experience.
|
||||
Feel free to ask me anything!
|
||||
</p>
|
||||
</motion.div>
|
||||
);
|
||||
}
|
||||
|
||||
export default ChatMessage;
|
||||
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"status": "failed",
|
||||
"failedTests": [
|
||||
"b15d6361b2fc38288977-cc6cca7f3eb8cd82590c",
|
||||
"b15d6361b2fc38288977-5e1c665e664697d61b48",
|
||||
"b15d6361b2fc38288977-61ae5d34d2c913db9b2a",
|
||||
"b15d6361b2fc38288977-284f9ff9499f4f985752",
|
||||
"b15d6361b2fc38288977-554360e215668a72f3c5",
|
||||
"b15d6361b2fc38288977-d4fe6d5b85e4848564f5",
|
||||
"b15d6361b2fc38288977-e6c0964e023326d4a6c7",
|
||||
"b15d6361b2fc38288977-252e2d4a1453fc1d2a15",
|
||||
"b15d6361b2fc38288977-e2864a9c91ff6b5e2798"
|
||||
]
|
||||
}
|
||||
+301
@@ -0,0 +1,301 @@
|
||||
# Page snapshot
|
||||
|
||||
```yaml
|
||||
- generic [active] [ref=e1]:
|
||||
- generic [ref=e2]:
|
||||
- generic:
|
||||
- img
|
||||
- navigation "Main navigation" [ref=e5]:
|
||||
- generic [ref=e7]:
|
||||
- link "Damjan Savić Logo" [ref=e8] [cursor=pointer]:
|
||||
- /url: /de
|
||||
- img "Damjan Savić Logo" [ref=e9]
|
||||
- generic [ref=e10]:
|
||||
- link "Startseite" [ref=e11] [cursor=pointer]:
|
||||
- /url: /de
|
||||
- img [ref=e12]
|
||||
- generic [ref=e15]: Startseite
|
||||
- link "Über mich" [ref=e16] [cursor=pointer]:
|
||||
- /url: /de/about
|
||||
- img [ref=e17]
|
||||
- generic [ref=e20]: Über mich
|
||||
- link "Leistungen" [ref=e21] [cursor=pointer]:
|
||||
- /url: /de/leistungen
|
||||
- img [ref=e22]
|
||||
- generic [ref=e33]: Leistungen
|
||||
- link "Portfolio" [ref=e34] [cursor=pointer]:
|
||||
- /url: /de/portfolio
|
||||
- img [ref=e35]
|
||||
- generic [ref=e38]: Portfolio
|
||||
- link "Blog" [ref=e39] [cursor=pointer]:
|
||||
- /url: /de/blog
|
||||
- img [ref=e40]
|
||||
- generic [ref=e42]: Blog
|
||||
- link "Kontakt" [ref=e43] [cursor=pointer]:
|
||||
- /url: /de/contact
|
||||
- img [ref=e44]
|
||||
- generic [ref=e46]: Kontakt
|
||||
- generic [ref=e48]:
|
||||
- button "Select language" [ref=e49] [cursor=pointer]:
|
||||
- img [ref=e50]
|
||||
- generic [ref=e53]: Deutsch
|
||||
- listbox "Languages":
|
||||
- generic:
|
||||
- option "English"
|
||||
- option "Deutsch" [selected]
|
||||
- option "Srpski"
|
||||
- main [ref=e54]:
|
||||
- generic [ref=e55]:
|
||||
- img "Damjan Savić" [ref=e57]
|
||||
- generic [ref=e59]:
|
||||
- link "LinkedIn" [ref=e60] [cursor=pointer]:
|
||||
- /url: https://www.linkedin.com/in/damjan-savi%C4%87-720288127/
|
||||
- img [ref=e61]
|
||||
- link "GitHub" [ref=e65] [cursor=pointer]:
|
||||
- /url: https://github.com/damjan1996
|
||||
- img [ref=e66]
|
||||
- generic [ref=e70]:
|
||||
- paragraph [ref=e71]: FULLSTACK DEVELOPER
|
||||
- heading "DAMJAN SAVIC|" [level=1] [ref=e72]
|
||||
- paragraph [ref=e73]: Entwicklung von KI-Agenten und Automatisierungslösungen. Von Voice-AI-Plattformen bis zu autonomen Web-Agenten.
|
||||
- generic [ref=e74]:
|
||||
- link "KONTAKT AUFNEHMEN" [ref=e75] [cursor=pointer]:
|
||||
- /url: mailto:info@damjan-savic.com
|
||||
- link "PROJEKTE" [ref=e76] [cursor=pointer]:
|
||||
- /url: "#projects"
|
||||
- navigation [ref=e77]:
|
||||
- link "ERFAHRUNG" [ref=e78] [cursor=pointer]:
|
||||
- /url: "#experience"
|
||||
- link "FÄHIGKEITEN" [ref=e79] [cursor=pointer]:
|
||||
- /url: "#skills"
|
||||
- link "ÜBER MICH" [ref=e80] [cursor=pointer]:
|
||||
- /url: "#about"
|
||||
- img [ref=e82]
|
||||
- generic [ref=e86]:
|
||||
- heading "Berufserfahrung" [level=2] [ref=e87]
|
||||
- generic [ref=e89]:
|
||||
- generic [ref=e90]:
|
||||
- heading "Process Automation Specialist" [level=3] [ref=e91]
|
||||
- heading "Everlast Consulting GmbH" [level=4] [ref=e92]
|
||||
- paragraph [ref=e93]: 12/2024 - HEUTE
|
||||
- list [ref=e94]:
|
||||
- listitem [ref=e95]:
|
||||
- generic [ref=e96]: →
|
||||
- generic [ref=e97]: Entwicklung von KI-Agenten mit n8n und Zapier
|
||||
- listitem [ref=e98]:
|
||||
- generic [ref=e99]: →
|
||||
- generic [ref=e100]: Aufbau von Web-Scraping-Lösungen
|
||||
- listitem [ref=e101]:
|
||||
- generic [ref=e102]: →
|
||||
- generic [ref=e103]: Migration von Power Automate zu n8n
|
||||
- generic [ref=e104]:
|
||||
- heading "Consultant Digital Solutions" [level=3] [ref=e105]
|
||||
- heading "Ritter Digital GmbH" [level=4] [ref=e106]
|
||||
- paragraph [ref=e107]: 08/2023 - 11/2024
|
||||
- list [ref=e108]:
|
||||
- listitem [ref=e109]:
|
||||
- generic [ref=e110]: →
|
||||
- generic [ref=e111]: Backend-Services auf dedizierten Servern
|
||||
- listitem [ref=e112]:
|
||||
- generic [ref=e113]: →
|
||||
- generic [ref=e114]: KI-Integration via Power Automate
|
||||
- listitem [ref=e115]:
|
||||
- generic [ref=e116]: →
|
||||
- generic [ref=e117]: RFID/IoT-Lösungen mit Zebra-Hardware
|
||||
- generic [ref=e118]:
|
||||
- button "Previous page" [disabled] [ref=e119]: ‹
|
||||
- generic [ref=e120]:
|
||||
- button "Page 1" [ref=e121] [cursor=pointer]
|
||||
- button "Page 2" [ref=e123] [cursor=pointer]
|
||||
- button "Next page" [ref=e125] [cursor=pointer]: ›
|
||||
- generic [ref=e128]:
|
||||
- heading "Fähigkeiten" [level=2] [ref=e129]
|
||||
- generic [ref=e130]:
|
||||
- generic [ref=e131]:
|
||||
- generic [ref=e132]:
|
||||
- generic [ref=e133]:
|
||||
- generic [ref=e134]: AI & LLMs
|
||||
- generic [ref=e135]: 90%
|
||||
- progressbar [ref=e136]
|
||||
- generic [ref=e137]:
|
||||
- generic [ref=e138]:
|
||||
- generic [ref=e139]: Automation
|
||||
- generic [ref=e140]: 85%
|
||||
- progressbar [ref=e141]
|
||||
- generic [ref=e142]:
|
||||
- generic [ref=e143]:
|
||||
- generic [ref=e144]: Python
|
||||
- generic [ref=e145]: 90%
|
||||
- progressbar [ref=e146]
|
||||
- generic [ref=e147]:
|
||||
- generic [ref=e148]:
|
||||
- generic [ref=e149]: TypeScript
|
||||
- generic [ref=e150]: 85%
|
||||
- progressbar [ref=e151]
|
||||
- generic [ref=e152]:
|
||||
- generic [ref=e153]:
|
||||
- generic [ref=e154]: Datenbank
|
||||
- generic [ref=e155]: 85%
|
||||
- progressbar [ref=e156]
|
||||
- generic [ref=e157]:
|
||||
- generic [ref=e158]:
|
||||
- generic [ref=e159]: DevOps
|
||||
- generic [ref=e160]: 75%
|
||||
- progressbar [ref=e161]
|
||||
- generic [ref=e162]:
|
||||
- button "AI & LLMs" [ref=e164] [cursor=pointer]:
|
||||
- img [ref=e166]
|
||||
- generic [ref=e169]: AI & LLMs
|
||||
- button "Automation" [ref=e171] [cursor=pointer]:
|
||||
- img [ref=e173]
|
||||
- generic [ref=e177]: Automation
|
||||
- button "Python" [ref=e179] [cursor=pointer]:
|
||||
- img [ref=e181]
|
||||
- generic [ref=e185]: Python
|
||||
- button "TypeScript" [ref=e187] [cursor=pointer]:
|
||||
- img [ref=e189]
|
||||
- generic [ref=e194]: TypeScript
|
||||
- button "Datenbank" [ref=e196] [cursor=pointer]:
|
||||
- img [ref=e198]
|
||||
- generic [ref=e202]: Datenbank
|
||||
- button "DevOps" [ref=e204] [cursor=pointer]:
|
||||
- img [ref=e206]
|
||||
- generic [ref=e209]: DevOps
|
||||
- generic [ref=e211]:
|
||||
- generic [ref=e212]:
|
||||
- heading "Portfolio" [level=2] [ref=e213]
|
||||
- link "Alle Projekte" [ref=e214] [cursor=pointer]:
|
||||
- /url: /de/portfolio
|
||||
- generic [ref=e215]:
|
||||
- link "AI Document Reader 2024-01 4 Technologies AI Document Reader KI-gestützte Dokumentenanalyse mit OLLAMA und Python Python OLLAMA FastAPI +1 more" [ref=e216] [cursor=pointer]:
|
||||
- /url: /de/portfolio/ai-data-reader
|
||||
- generic [ref=e217]:
|
||||
- img "AI Document Reader" [ref=e219]
|
||||
- generic [ref=e220]:
|
||||
- generic [ref=e221]:
|
||||
- generic [ref=e222]:
|
||||
- img [ref=e223]
|
||||
- generic [ref=e225]: 2024-01
|
||||
- generic [ref=e226]:
|
||||
- img [ref=e227]
|
||||
- generic [ref=e230]: 4 Technologies
|
||||
- heading "AI Document Reader" [level=3] [ref=e231]
|
||||
- paragraph [ref=e232]: KI-gestützte Dokumentenanalyse mit OLLAMA und Python
|
||||
- generic [ref=e233]:
|
||||
- generic [ref=e234]: Python
|
||||
- generic [ref=e235]: OLLAMA
|
||||
- generic [ref=e236]: FastAPI
|
||||
- generic [ref=e237]: +1 more
|
||||
- img [ref=e239]
|
||||
- link "Smart Warehouse RFID 2024-02 4 Technologies Smart Warehouse RFID RFID-basiertes Lagerverwaltungssystem mit IoT-Integration Python RFID IoT +1 more" [ref=e243] [cursor=pointer]:
|
||||
- /url: /de/portfolio/smart-warehouse
|
||||
- generic [ref=e244]:
|
||||
- img "Smart Warehouse RFID" [ref=e246]
|
||||
- generic [ref=e247]:
|
||||
- generic [ref=e248]:
|
||||
- generic [ref=e249]:
|
||||
- img [ref=e250]
|
||||
- generic [ref=e252]: 2024-02
|
||||
- generic [ref=e253]:
|
||||
- img [ref=e254]
|
||||
- generic [ref=e257]: 4 Technologies
|
||||
- heading "Smart Warehouse RFID" [level=3] [ref=e258]
|
||||
- paragraph [ref=e259]: RFID-basiertes Lagerverwaltungssystem mit IoT-Integration
|
||||
- generic [ref=e260]:
|
||||
- generic [ref=e261]: Python
|
||||
- generic [ref=e262]: RFID
|
||||
- generic [ref=e263]: IoT
|
||||
- generic [ref=e264]: +1 more
|
||||
- img [ref=e266]
|
||||
- link "Portfolio mit KI 2024-03 4 Technologies Portfolio mit KI Moderne Portfolio-Website mit KI-Integration Next.js TypeScript Tailwind +1 more" [ref=e270] [cursor=pointer]:
|
||||
- /url: /de/portfolio/website-mit-ki
|
||||
- generic [ref=e271]:
|
||||
- img "Portfolio mit KI" [ref=e273]
|
||||
- generic [ref=e274]:
|
||||
- generic [ref=e275]:
|
||||
- generic [ref=e276]:
|
||||
- img [ref=e277]
|
||||
- generic [ref=e279]: 2024-03
|
||||
- generic [ref=e280]:
|
||||
- img [ref=e281]
|
||||
- generic [ref=e284]: 4 Technologies
|
||||
- heading "Portfolio mit KI" [level=3] [ref=e285]
|
||||
- paragraph [ref=e286]: Moderne Portfolio-Website mit KI-Integration
|
||||
- generic [ref=e287]:
|
||||
- generic [ref=e288]: Next.js
|
||||
- generic [ref=e289]: TypeScript
|
||||
- generic [ref=e290]: Tailwind
|
||||
- generic [ref=e291]: +1 more
|
||||
- img [ref=e293]
|
||||
- generic [ref=e299]:
|
||||
- generic [ref=e300]:
|
||||
- heading "Über Damjan Savić - Senior Fullstack Entwickler & Digital Solutions Consultant" [level=2] [ref=e302]
|
||||
- generic [ref=e304]:
|
||||
- generic [ref=e305]:
|
||||
- img [ref=e307]
|
||||
- generic [ref=e310]: Köln, Deutschland
|
||||
- generic [ref=e311]:
|
||||
- img [ref=e313]
|
||||
- generic [ref=e316]: 5+ Jahre Erfahrung
|
||||
- generic [ref=e317]:
|
||||
- img [ref=e319]
|
||||
- generic [ref=e322]: Full-Stack Developer
|
||||
- generic [ref=e323]:
|
||||
- img [ref=e325]
|
||||
- generic [ref=e328]: ERP Spezialist
|
||||
- paragraph [ref=e330]: Damjan Savić ist AI & Automation Specialist mit Fokus auf Voice AI, autonome Agenten und Prozessautomatisierung. Mit einem M.A. in Software Development und über 7 Jahren Erfahrung in der Entwicklung digitaler Lösungen verbindet er technische Expertise mit strategischem Geschäftsverständnis.
|
||||
- generic [ref=e331]:
|
||||
- link "Mehr erfahren" [ref=e332] [cursor=pointer]:
|
||||
- /url: /de/about
|
||||
- img [ref=e333]
|
||||
- text: Mehr erfahren
|
||||
- link "CV herunterladen" [ref=e336] [cursor=pointer]:
|
||||
- /url: /damjan_savic_cv_de.pdf
|
||||
- img [ref=e337]
|
||||
- text: CV herunterladen
|
||||
- img "Damjan Savić" [ref=e342]
|
||||
- contentinfo [ref=e343]:
|
||||
- generic [ref=e345]:
|
||||
- generic [ref=e346]:
|
||||
- heading "Kontakt" [level=3] [ref=e347]
|
||||
- generic [ref=e348]:
|
||||
- link "info@damjan-savic.com" [ref=e349] [cursor=pointer]:
|
||||
- /url: mailto:info@damjan-savic.com
|
||||
- img [ref=e350]
|
||||
- generic [ref=e353]: info@damjan-savic.com
|
||||
- generic [ref=e354]:
|
||||
- img [ref=e355]
|
||||
- generic [ref=e358]: Köln, Deutschland
|
||||
- generic [ref=e359]:
|
||||
- heading "Navigation" [level=3] [ref=e360]
|
||||
- navigation [ref=e361]:
|
||||
- link "Portfolio" [ref=e362] [cursor=pointer]:
|
||||
- /url: /de/portfolio
|
||||
- link "Blog" [ref=e363] [cursor=pointer]:
|
||||
- /url: /de/blog
|
||||
- link "Über mich" [ref=e364] [cursor=pointer]:
|
||||
- /url: /de/about
|
||||
- link "Kontakt" [ref=e365] [cursor=pointer]:
|
||||
- /url: /de/contact
|
||||
- generic [ref=e366]:
|
||||
- heading "Social Media" [level=3] [ref=e367]
|
||||
- generic [ref=e368]:
|
||||
- link "LinkedIn" [ref=e369] [cursor=pointer]:
|
||||
- /url: https://www.linkedin.com/in/damjan-savić-720288127/
|
||||
- img [ref=e370]
|
||||
- link "GitHub" [ref=e374] [cursor=pointer]:
|
||||
- /url: https://github.com/damjan1996
|
||||
- img [ref=e375]
|
||||
- generic [ref=e379]:
|
||||
- paragraph [ref=e380]: © 2026 Damjan Savić. Alle Rechte vorbehalten
|
||||
- generic [ref=e381]:
|
||||
- link "Datenschutz" [ref=e382] [cursor=pointer]:
|
||||
- /url: /de/privacy
|
||||
- link "Impressum" [ref=e383] [cursor=pointer]:
|
||||
- /url: /de/imprint
|
||||
- link "AGB" [ref=e384] [cursor=pointer]:
|
||||
- /url: /de/terms
|
||||
- button "Open Next.js Dev Tools" [ref=e390] [cursor=pointer]:
|
||||
- img [ref=e391]
|
||||
- alert [ref=e394]
|
||||
```
|
||||
BIN
Binary file not shown.
|
After Width: | Height: | Size: 377 KiB |
Reference in New Issue
Block a user