This is a submission for the New Year, New You Portfolio Challenge Presented by Google AI
About Me
My professional path isn't linear. It's atypical, composed of pivots, skill acquisitions across different contexts, and transitions that traditional CVs struggle to represent.
For years, the challenge wasn't "how to write a CV" but rather: how to make a non-linear journey readable?
The classic portfolio format—chronological, linear, static—works well for continuous trajectories. It breaks down for everything else. This project emerged from that personal need: what if we stopped trying to flatten our careers into a timeline, and instead represented them as they truly are—a network of interconnected skills, projects, and experiences?
As we enter 2026, "New Year, New You" doesn't have to mean reinventing yourself. Sometimes it means representing yourself more accurately.
Portfolio
Live Demo: AI Knowledge Graph CV Builder
What You'll See
The app loads with my CV as a demo so you can explore immediately:
- Network Graph: 30+ interconnected nodes showing skills, projects, and expertise domains
- Flow Diagram: Visual journey from skills → projects → specialized areas
- Skills Matrix: Heatmap showing which projects use which technologies
Zero friction: No upload required to see it in action. Click "Upload Your Own CV" when you want to try yours.
Visualizing Career Evolution
To test the system's ability to capture career trajectories, I ran my own CV from 2021 vs 2025:
2021 Graph (37 nodes, 74 edges):
- Corporate-focused: Skyrock, Logic-Immo, Photobox
- Legacy tech: Flash/Zend_Amf, Palm webOS, ORACLE
- Broader scope: Lead Dev, Project Manager, Full-Stack Engineer
2025 Graph (30 nodes, 74 edges, +23% density):
- Independent: Freelance + personal projects
- Modern stack: Astro, LLM/RAG, Docker, PostgreSQL
- Focused expertise: Migration Engineering + AI Automation
What changed?
- -8 technologies (legacy tech retired)
- +2 concepts (AI Automation, Migration Engineering)
- +23% density (deeper specialization vs wider breadth)
The graph doesn't just show skills—it tells the story of a career pivot from corporate generalist to independent specialist.
This is exactly what traditional CVs fail to capture.
Career Evolution: 2021 → 2025
| Metric | 2021 | 2025 | Change |
|---|---|---|---|
| Nodes | 37 | 30 | -19% ↓ |
| Edges | ~74 | 74 | = |
| Density | 2.0 | 2.2 | +23% ↑ |
| Stack | Legacy + Modern | Modern only | 🔄 |
| Focus | Corporate generalist | Independent specialist | 🎯 |
Key transitions:
- Out: Flash, ORACLE, Palm webOS, 5 corporate clients
- In: Astro, LLM/RAG, Docker, AI Automation, Migration Engineering
- Evolved: PHP 4→7, WordPress (legacy→modern), MySQL
The graph doesn't just track skills—it reveals strategic pivots.
Real-World Testing
I tested the tool with three different profiles:
Senior Specialist (30 nodes, 2.47 density)
- Deep expertise in AI/Migration
- Modern stack (Astro, LLM, Docker)
- High interconnection within niche
Mid-Level Generalist (33 nodes, 2.42 density)
- Broad CMS expertise (WordPress, Magento, PrestaShop)
- Traditional e-commerce stack
- Skills distributed across varied projects
Junior Polyvalent (35 nodes, 2.57 density)
- Modern full-stack (MERN, Angular, Symfony)
- Creative skills (design, video)
- The matrix revealed interesting gaps: claimed Symfony expertise with no projects demonstrating it
Key insight: The tool adapts to different career stages and reveals actionable patterns—like skills declared but not proven in projects.
How I Built It
The Problem: Structure, Not Extraction
This isn't keyword extraction. It's about asking AI to reason about context and produce a structured representation: nodes, relationships, and a graph-oriented vision.
Most CV parsers extract surface-level keywords. This project asks: "What are the semantic connections between my Python skills, my migration projects, and my AI automation expertise?"
Tech Stack
AI Layer:
- Gemini Flash Preview 3.0 for CV analysis
- Google AI Studio for prompt engineering & iteration
- Custom system prompt with 6 levels of extraction rules
Visualization Layer:
- Streamlit for the web interface (rapid prototyping)
- vis.js (via streamlit-agraph) for network graphs
- Plotly for Sankey flow diagrams & heatmaps
Deployment:
- Google Cloud Run for containerized deployment (challenge requirement)
- Docker for containerization
- GitHub integration for CI/CD
Why streamlit-agraph for Network Visualization?
The Network Graph view uses streamlit-agraph (a vis.js wrapper). During development, I evaluated several alternatives for displaying interactive network graphs in Streamlit. Here's the decision matrix that led to this choice:
| Library | Responsive | Interactive | Force-Directed Layout | Dev Time | Verdict |
|---|---|---|---|---|---|
| streamlit-agraph | ⚠️ Fixed canvas | ✅ Full (click, zoom, pan) | ✅ Automatic | ~2 hours | ✅ Selected |
| Plotly Graph Objects | ✅ 100% responsive | ⚠️ Limited interactions | ❌ Manual positioning | ~6 hours | ❌ Too much effort |
| Pyvis | ⚠️ HTML file generation | ✅ Full | ✅ Automatic | ~4 hours | ❌ Complex integration |
| NetworkX + Matplotlib | ✅ Fully responsive | ❌ Static image | ✅ Automatic | ~3 hours | ❌ No interactivity |
| D3.js Custom | ✅ 100% responsive | ✅ Full control | ✅ Custom | ~8+ hours | ❌ Time prohibitive |
Decision rationale:
For this project, interactivity was the priority. The ability to click nodes, activate focus mode, and explore connections dynamically was more valuable than perfect responsive behavior in iframes.
streamlit-agraph delivered:
✅ Zero-configuration force-directed layout (nodes position themselves)
✅ Full interaction support (click handlers, zoom, pan)
✅ Production-ready in ~2 hours of development
✅ Professional visual quality out of the box
Trade-off accepted:
⚠️ Fixed canvas size (1400×900px) doesn't fill 100% of iframe width
✅ Mitigation: Canvas size chosen to work well on 1440px+ screens (laptops/desktops)
Alternative approaches considered (Plotly, D3.js) would have provided better responsive behavior but at the cost of 3-4× development time and reduced interactivity.
So streamlit-agraph hit the sweet spot between functionality, visual quality, and development speed.
Note: For optimal experience, open the full application directly.
Responsive Strategy
While the canvas is fixed at 1400×900px, users can collapse the sidebar (<< button) to gain ~250px of vertical space. This makes the app work perfectly even on 1366-1680px screens.
- Sidebar open: Full controls + graph (optimal on 1920px+)
- Sidebar closed: Full-screen graph (optimal on 1366px+)
User-controlled responsiveness proved more practical than attempting CSS magic with fixed-size canvas elements.
Development Process
1. Prompt Engineering in Google AI Studio
Before writing any application code, I spent time in AI Studio crafting the extraction prompt. This phase was critical:
LEVEL 1: Core entities (Person, Skills, Projects)
LEVEL 2: Relationships (USES, CREATED, MASTERS)
LEVEL 3: Technical relationships (PHP ENABLES WordPress)
LEVEL 4: Concepts & expertise domains
LEVEL 5: Temporal & contextual relationships
LEVEL 6: Bidirectional concept-project links ← Key innovation
Why this matters: A CV isn't just nodes, it's the connections that matter. "Python" isn't just a skill—it ENABLES AI Automation, which is IMPLEMENTED_IN multiple projects, which DEMONSTRATES Migration Engineering expertise.
The prompt evolved through 20+ iterations in AI Studio before integration.
2. Multi-View Dashboard
Initial version had only the network graph. User feedback revealed a problem: different audiences need different views.
- Developers want to explore connections (Network Graph)
- Recruiters need quick visual narratives (Flow Diagram)
- Managers want fast skill scanning (Skills Matrix)
The breakthrough was realizing this isn't three separate features—it's three perspectives on the same data.
3. Iterative UX Refinement
Based on real user testing:
- V7.0: Multi-view dashboard
- V7.1-V7.6: Spacing optimization (nodes were overlapping)
- V8.0-V8.2: English interface + demo auto-loading
The demo CV auto-load was inspired by the challenge theme: show, don't tell. Let visitors see the result instantly instead of asking them to upload first.
4. Deployment on Google Cloud Run
As required by the challenge, the app is deployed on Google Cloud Run. The deployment is straightforward:
- Containerized: Streamlit app packaged in Docker
- Serverless: Auto-scaling, pay-per-use
- Public URL: Accessible without authentication
- CI/CD: Connected to GitHub for automatic deployments
Cloud Run was chosen for its simplicity and alignment with the Google AI ecosystem.
Google AI Tools Used
Google AI Studio was essential for:
- Rapid prompt iteration without deploying code
- JSON validation to ensure consistent output structure
- Token optimization to stay within rate limits
Gemini Flash Preview 3.0 chosen for:
- Multimodal capabilities (PDF → structured JSON)
- Large context window (handles long CVs)
- Structured output with consistent formatting
- Speed for real-time extraction
Design Decisions
Why Graphs?
Traditional CVs are tree structures (chronological). Professional identities are graphs (relational). The mismatch creates information loss.
Example: My "WordPress to Astro Migration" project connects to:
- Astro framework (USES)
- WordPress (USES)
- Web Performance (DEMONSTRATES)
- Migration Engineering (DEMONSTRATES)
- SSG Ecosystem (IMPLEMENTED_IN)
A timeline can't represent this richness. A graph can.
Why Three Visualizations?
Network Graph: For exploration and discovery
- Best for: Deep dives, understanding connections
- Audience: Technical leads, fellow developers
Flow Diagram: For storytelling
- Best for: Quick pitches, visual narratives
- Audience: Recruiters, hiring managers
Skills Matrix: For scanning
- Best for: 30-second skill assessment
- Audience: HR, technical screeners
One visualization can't serve all audiences. This was the key insight.
Why Demo-First?
Inspired by product design principles: reduce friction to zero.
Before: "Upload your CV to see how it works" → 50% bounce rate
After: "Here's mine already loaded, explore now" → Instant engagement
What I'm Most Proud Of
1. Bidirectional Semantic Relationships
The graph doesn't just show that "Newsletter Engine uses Python"—it shows that:
- Python ENABLES AI Automation (capability)
- AI Automation is IMPLEMENTED_IN Newsletter Engine (evidence)
- Newsletter Engine DEMONSTRATES AI Automation (showcase)
This bidirectionality creates semantic completeness. Each project isn't just a container of technologies—it's proof of conceptual expertise.
2. Dense Graph Quality (70+ Relationships)
Most CV extractors produce sparse graphs (1.0-1.5 edges per node). This achieves density 2.4 (72 relationships for 30 nodes) by:
- Extracting ALL mentioned technologies (not just "main" skills)
- Creating technology chains (Docker RUNS_ON Linux)
- Linking related projects (wp2md RELATED_TO WordPress Migration)
A dense graph is a truthful graph.
3. Zero-Config Demo Experience
The app loads with my CV pre-analyzed. No authentication, no API keys to configure, no upload required.
This aligns with "New Year, New You"—the portfolio shows transformation immediately rather than promising it.
4. Real-Time Adaptation to Feedback
Every version (V1 → V8.2) incorporated user feedback:
- "Nodes overlap" → Mega Wide spacing mode
- "Labels unreadable" → Verdana sans-serif, size optimization
- "Need different views" → Multi-view dashboard
- "Too much friction" → Demo auto-loading
Built in public, refined through dialogue.
5. Technical Elegance
The entire extraction happens in a single prompt. No multi-stage pipeline, no external tools.
response = model.generate_content([
{"mime_type": "application/pdf", "data": cv_bytes},
EXTRACTION_PROMPT
])
graph_data = json.loads(response.text)
Input: PDF bytes + prompt
Output: Complete knowledge graph
That's it. The complexity is in the prompt design (crafted in AI Studio), not the code.
Personal Reflection: New Year, New Perspective
This project started as a personal need and became something more: an invitation to view professional identity differently.
We spend so much energy trying to fit our careers into templates. What if the template was wrong?
A knowledge graph doesn't judge whether your path was "correct." It simply represents what is: the skills you have, the projects you built, and how they connect.
In the spirit of "New Year, New You," this isn't about reinventing yourself. It's about representing yourself with more accuracy. Sometimes that's enough.
Try It Yourself
🔗 Live App: knowledge-graph-cv-837592265234.europe-west1.run.app
My CV is loaded by default—explore the three views, then upload your own.
📂 Source Code: https://github.com/pcescato/knowledge-graph-cv
Technical Metrics
- Extraction Time: ~15-25 seconds (Gemini Flash Preview 3.0)
- Average Graph: 25-35 nodes, 60-80 relationships
- Density: 2.0-2.8 (edges per node)
- Supported Formats: PDF only
- Visualizations: 3 (Network, Flow, Matrix)
- Languages: English interface
What's Next?
This MVP was built in 3 days as a proof of concept for the Google AI Challenge.
Technical roadmap (not yet implemented):
- Export formats: JSON, GraphML, Neo4j cypher for data portability
- Comparison mode: Side-by-side CV analysis to track career evolution
- Skill gap analysis: Compare your graph against target job descriptions
- Temporal dimension: Visualize career progression over time
But I see potential beyond personal portfolios:
- HR Tech: Intelligent candidate matching based on skill graphs, not keywords
- Internal Talent Mapping: Companies understanding who knows what across teams
- Career Coaching: Visualizing skill gaps and growth paths
The graph-based approach reveals connections that traditional CVs hide. If you're building in this space or interested in exploring applications for recruitment, talent analytics, or knowledge management—I'd love to chat.
The FinOps Victory: Slashing my Cloud Bill by 97% Against a Botnet
The biggest challenge of this project wasn't the AI—it was budgetary survival. Within 48 hours, my application went from a quiet demo to the target of an intensive piloning (bots from Poland, Vietnam, and the USA).
The Final Architecture: The "Thermal Shield"
The problem? Streamlit (Python) is notoriously bad at closing persistent WebSocket connections quickly, which kept my Cloud Run instances running (and billing) indefinitely.
The solution: Injecting a Caddy server (written in Go) as a Reverse Proxy inside the same Cloud Run container.
Cloud Run Container (512Mi)
├── Caddy (:8080) ← The "Bouncer" at the door
│ ├── IP Filtering (via X-Forwarded-For headers) → 403 Forbidden
│ └── Proxy legitimate traffic → localhost:8501
└── Streamlit (:8501) ← The (now protected) App
The Numbers (Last Hour Report)
Using a custom monitoring script, I isolated the efficiency of this defense during a high-traffic hour:
| Traffic Type | Requests | Action | CPU Time | Projected Budget |
|---|---|---|---|---|
| Bot Attacks | 945 | Blocked (403) | 2.17s | €0.01 / month |
| Human Sessions | 12 | Allowed (101) | 328.68s | €1.58 / month |
| TOTAL | 957 | - | 330.85s | €1.59 / month ✅ |
Cost Evolution (Monthly Projection)
Day 1 (Initial Deploy): ~€25/mo (No protection).
Day 3 (Attack Detected): ~€42/mo (Python-level filtering failed to close sockets).
Day 6 (Caddy "Sniper" Active): €1.59/mo (Bots are ejected in under 2ms).
Drastic Reduction: -96% from the worst-case scenario.
Lessons Learned "From the Trenches"
The App is not a Firewall: In Serverless environments, if traffic hits your Python code, you’ve already paid. You must block the attack as early as possible in the network stack.
The IPv6 Trap: Modern bots use IPv6 tunnels extensively (Comcast, Indian ISPs) which bypass traditional IPv4 filters.
The Internal Sidecar: Running two processes (Caddy + Streamlit) in a single container is an elegant, free, and ultra-robust way to secure a public demo without the cost of a Load Balancer or Cloud Armor.
The irony of the challenge: I probably learned more about reverse proxies, X-Forwarded-For headers, and cloud cost optimization than I did about Knowledge Graphs. But that's the reality of production: **Production > Tutorials, always.
The full story: Why Streamlit + Cloud Run is a Billing Trap (and How I Fixed It)
Thanks for reading! If this resonates with you, I'd love to hear your thoughts.
Does your career fit into a timeline, or is it a graph? 💭



Top comments (20)
Pascal, that’s an absolutely brilliant idea - a CV as a skills graph! I honestly never thought about it that way, and it really is genius; that’s exactly how we grow. Well, I don’t want to worry you, but I guess you can’t stop writing your blog after all - your ideas are just too good!
Careful, you’re dangerously close to convincing me 😄
I’ll admit: once you start thinking about careers as graphs, it’s hard to unsee it.
Thanks for the kind words — they definitely make the writing pause feel… flexible.
By the way: did you try with yours?
Ah, not yet. I’ve given myself too many tasks for January and now I have to somehow deal with them 😅
Haha, that sounds very familiar 😄
January does have that “let’s do everything at once” energy.
No rush at all — if you ever feel like feeding one task into another, I’ll be curious to see what your graph looks like.
Very creative, indeed, but does it not focus a bit too much on how to express it, rather than how to interpret it?
Hiring managers need certain questions to be answered, otherwise they'll risk making some totally wrong hires:
That’s a very fair question — and I actually agree with most of it.
This project deliberately focuses on representation, not evaluation. It doesn’t try to answer hiring questions directly, and it shouldn’t replace interviews, references, or human judgment.
What it tries to surface is something more upstream: structure.
Patterns of focus, evolution, depth vs. breadth, long-term coherence, or sudden buzzword spikes become visible in ways a linear CV often hides.
All the questions you list — fundamentals, communication, initiative, collaboration, honesty, even toxicity — still require human interaction. A graph can’t (and shouldn’t) “score” those.
But as a complementary view, it can help frame better conversations:
why certain technologies persist, why others disappear, where real depth might be worth probing, or where something looks inflated and deserves scrutiny.
In that sense, it’s less about making hiring decisions and more about asking better questions — earlier, and with fewer blind spots.
And yes, the risk of AI-generated CVs is real. Ironically, that’s also why alternative representations may become more useful: consistency over time, evolution across versions, and structural coherence are harder to fake than polished bullet points.
So I see this less as a hiring tool, and more as a lens — one that still requires humans on both sides to do the actual thinking.
Hello, Paskal.
Wishing you a year filled with growth, health, and success. 🌟
I was waiting for your post.
This is really strong work, both technically and conceptually. You’ve put clear language around something a lot of people with non-linear careers feel but don’t usually know how to describe: how much meaning gets lost when years of connected experience are forced into a simple timeline. Thinking about professional identity as a graph instead of a sequence is a genuinely useful shift, and the way you ground it—through density, two-way relationships, and how things evolve over time—keeps it practical rather than theoretical. The demo-first choice also shows good product sense. It lets people immediately understand the value without needing a lot of explanation or buy-in.
On the technical side, the restraint really comes through. Pushing complexity into prompt design instead of code, choosing tools based on how they actually improve interaction, and being upfront about the trade-offs all point to mature decision-making. The idea of showing the same data through different views for different audiences is especially strong, and it feels useful well beyond portfolios—things like HR tools, internal talent mapping, or career coaching come to mind. Overall, this doesn’t just show a product; it reflects a thoughtful way of thinking about careers, data, and AI that feels current and genuinely applicable.
Thank you, Art, for such a deep and thoughtful reading! You hit the nail on the head regarding my main motivation: the frustration of seeing rich, interconnected career paths flattened into a simple, lossy timeline.
Your point about use cases beyond the portfolio—like HR tools, talent mapping, or coaching—is particularly interesting. Shifting the focus toward graph density and semantic connections instead of just duration really does change how we perceive professional potential.
Also, glad the 'show, don't tell' approach resonated. It was a deliberate product choice to let the data speak for itself immediately. Much appreciated!
Very jaw dropping stuff! never thought about showing my developer knowlage as graph, specially using Neo4j! will def make something simulator. also very interesting stuff about using caddy in the cloud run!!
Thanks!
I had the same reaction when I first sketched the idea: once you stop forcing a career into a linear timeline, the graph almost builds itself. Neo4j-style thinking fits surprisingly well for skills and roles — the relationships tell a bigger story than the dates.
And yes, running Caddy on Cloud Run is a fun combo. It removes a lot of friction when you want to ship quickly with clean routing.
If you end up experimenting with your own graph, I’d really love to see what direction you take it in.
Already on it! you sent me straight down a rabbit hole 😄
I’ve just installed Neo4j and started mapping things out from my portfolio. It’s surprisingly satisfying to see the connections emerge once you stop thinking linearly.
That’s the best part — once you drop the linear mindset, the patterns almost reveal themselves.
Curious to see where your graph takes you next.
That's a great idea!
Not for this challenge, but because of my own struggles with recruitment (on both sides over the years), I've built a self-updating developers' portfolio!
Don't want to intercept your thread so won't post here unless asked for ;)
That sounds really interesting 🙂
And no worries at all about “intercepting” — sharing experiences like that is exactly what makes these discussions valuable.
If you ever feel like expanding on it, I’d genuinely be curious to hear how you approached it.
Cool! Thank you for sharing :)
Thanks! Curious to hear if you try it with your own CV -
would love feedback on what works / what doesn't 👍
No! I have not. I am going to a personal project with AI very soon. I am not sure if I am going to use Matplotlib or potly as graph. I am going to deploy my project on renders.
Nice! For graphs with AI projects, Plotly > Matplotlib if you need
interactivity. That's what I used here for Flow/Matrix views.
Good luck with your project! 🚀
Nice! Thank you :)
Some comments may only be visible to logged-in visitors. Sign in to view all comments.