-
-
- {project.isInfrastructure ? INFRA_ICON : DEFAULT_ICON}
-
-
- {project.title}
-
+ {/* Top: icon + title */}
+
+
+ {project.isInfrastructure ? INFRA_ICON : DEFAULT_ICON}
-
- {project.demoUrl && (
-
-
-
- )}
+
+ {project.title}
+
{/* Description */}
@@ -100,8 +78,34 @@ export function ProjectCard({ project, index }: ProjectCardProps) {
))}
+ {/* Action buttons */}
+ {(project.demoUrl || project.docsUrl) && (
+
+ )}
+
{/* Demo badge */}
- {project.demoUrl && (
+ {(project.isLive || project.demoUrl) && (
diff --git a/portfolio-view/src/components/projects/ProjectsSection.tsx b/portfolio-view/src/components/projects/ProjectsSection.tsx
index e7adc79..4672061 100644
--- a/portfolio-view/src/components/projects/ProjectsSection.tsx
+++ b/portfolio-view/src/components/projects/ProjectsSection.tsx
@@ -8,6 +8,9 @@ const PROJECTS: Project[] = [
description:
'API Gateway with JWT authentication, OAuth2 (Google, GitHub, Facebook), reactive routing, and per-user rate limiting built on Spring Cloud Gateway.',
stack: ['Java 25', 'Spring Boot 3.5', 'Spring Cloud Gateway', 'WebFlux', 'R2DBC', 'PostgreSQL', 'jjwt'],
+ isLive: true,
+ demoUrl: 'https://balexvic.com/ui/dc1/services',
+ demoLabel: 'Consul UI',
},
{
id: 'rag',
@@ -15,7 +18,10 @@ const PROJECTS: Project[] = [
description:
'AI-powered chat with document context. Upload PDF/DOCX, vector semantic search, BM25 reranking, and real-time SSE streaming responses.',
stack: ['Java 25', 'Spring Boot 3.5', 'Spring AI', 'pgvector', 'Kafka', 'TikaDocumentReader'],
- demoUrl: '/ragview/',
+ isLive: true,
+ demoUrl: 'https://balexvic.com/ragview/',
+ docsUrl: 'https://balexvic.com/api/rag/swagger-ui/index.html',
+ demoLabel: 'Open App',
},
{
id: 'analytics',
@@ -23,15 +29,18 @@ const PROJECTS: Project[] = [
description:
'Kafka consumer that aggregates platform events into PostgreSQL with a dynamic REST API supporting complex filtering and pagination.',
stack: ['Java 25', 'Spring Boot 3.5', 'Kafka', 'JPA', 'Flyway', 'JpaSpecificationExecutor'],
- demoUrl: '/analyticsview/',
+ isLive: true,
+ demoUrl: 'https://balexvic.com/analyticsview/',
+ demoLabel: 'Open App',
},
{
id: 'audio-foreign',
- title: 'Audio Foreign',
+ title: 'Learn Deutsch',
description:
'Voice-based language learning app: speak — get instant AI feedback. Speech-to-text via Whisper, grammar correction via Claude, playback via ElevenLabs.',
stack: ['Node.js', 'Express', 'OpenAI Whisper', 'Anthropic Claude API', 'ElevenLabs TTS'],
- demoUrl: '/deutsch/',
+ demoUrl: 'https://balexvic.com/deutsch/',
+ demoLabel: 'Open App',
},
{
id: 'infra',
diff --git a/portfolio-view/src/types/index.ts b/portfolio-view/src/types/index.ts
index 223e230..b820d69 100644
--- a/portfolio-view/src/types/index.ts
+++ b/portfolio-view/src/types/index.ts
@@ -4,6 +4,9 @@ export interface Project {
description: string
stack: string[]
demoUrl?: string
+ docsUrl?: string
+ demoLabel?: string
+ isLive?: boolean
isInfrastructure?: boolean
}