[{"data":1,"prerenderedAt":1591},["ShallowReactive",2],{"portfolio-en":3},[4,183,383,526,601,720,864,1004,1117,1234,1370,1443],{"id":5,"title":6,"body":7,"client":166,"date":167,"description":168,"extension":169,"featured":170,"meta":171,"navigation":170,"order":172,"path":173,"seo":174,"stem":175,"tags":176,"thumbnail":122,"__hash__":182},"portfolio_en\u002Fportfolio\u002Fen\u002Fsia.md","SIA — Incubator Platform for Science Park Skövde",{"type":8,"value":9,"toc":157},"minimark",[10,15,19,22,26,79,83,86,112,116,123,129,135,141,145,151],[11,12,14],"h2",{"id":13},"overview","Overview",[16,17,18],"p",{},"SIA (Science Park Skövde Incubator Application) is a comprehensive management system built to streamline the operations of Science Park Skövde's startup program. The system manages over 200 startups, tracking their journey from application through various phases to successful exit.",[16,20,21],{},"The project started in 2020 and is still in active development with continuous improvements.",[11,23,25],{"id":24},"what-the-system-does","What the system does",[27,28,29,37,43,49,55,61,67,73],"ul",{},[30,31,32,36],"li",{},[33,34,35],"strong",{},"Application Portal"," — Public-facing 7-step wizard with bilingual support (Swedish\u002FEnglish), file uploads, and team management",[30,38,39,42],{},[33,40,41],{},"Company Lifecycle"," — Track startups through Formation, Business, and Exit phases",[30,44,45,48],{},[33,46,47],{},"Coach Management"," — Assign and track business coach hours and interactions",[30,50,51,54],{},[33,52,53],{},"Financial Tracking"," — Revenue reporting, investment tracking, and verification management",[30,56,57,60],{},[33,58,59],{},"Communication Hub"," — Notifications, push messages, and CEO briefs",[30,62,63,66],{},[33,64,65],{},"Company Showcase"," — Public display for TV screens with auto-rotating presentations and real-time statistics",[30,68,69,72],{},[33,70,71],{},"Document Drive"," — 2GB cloud storage per company",[30,74,75,78],{},[33,76,77],{},"Data Analytics"," — Real-time dashboards and comprehensive reporting",[11,80,82],{"id":81},"technical-choices","Technical choices",[16,84,85],{},"The system is built as a pure SPA + API architecture with complete separation of frontend and backend:",[27,87,88,94,100,106],{},[30,89,90,93],{},[33,91,92],{},"Passwordless Authentication"," — Magic link-based login for simple and secure access",[30,95,96,99],{},[33,97,98],{},"Real-time Updates"," — SignalR for live notifications and instant updates",[30,101,102,105],{},[33,103,104],{},"Type Safety"," — Full TypeScript coverage with auto-generated API client",[30,107,108,111],{},[33,109,110],{},"Mobile First"," — Responsive design optimized for all devices",[11,113,115],{"id":114},"the-platform","The Platform",[16,117,118],{},[119,120],"img",{"alt":121,"src":122},"SIA Dashboard — KPIs, investment insights, and activity feed","\u002Fimages\u002Fportfolio\u002Fsia-dashboard.png",[16,124,125],{},[119,126],{"alt":127,"src":128},"Company profile with Innovation Readiness Level","\u002Fimages\u002Fportfolio\u002Fsia-company.png",[16,130,131],{},[119,132],{"alt":133,"src":134},"Company Directory — over 160 startups","\u002Fimages\u002Fportfolio\u002Fsia-directory.png",[16,136,137],{},[119,138],{"alt":139,"src":140},"Application Management with status pipeline","\u002Fimages\u002Fportfolio\u002Fsia-applications.png",[11,142,144],{"id":143},"tech-stack","Tech stack",[16,146,147,150],{},[33,148,149],{},"Frontend:"," Vue 3.5, TypeScript, PrimeVue, Tailwind CSS, Pinia, Vite, SignalR, Chart.js",[16,152,153,156],{},[33,154,155],{},"Backend:"," ASP.NET Core 9.0, C#, Entity Framework Core, SQL Server, SignalR, Serilog",{"title":158,"searchDepth":159,"depth":159,"links":160},"",2,[161,162,163,164,165],{"id":13,"depth":159,"text":14},{"id":24,"depth":159,"text":25},{"id":81,"depth":159,"text":82},{"id":114,"depth":159,"text":115},{"id":143,"depth":159,"text":144},"Science Park Skövde","2020-01-01","Comprehensive management system for Science Park Skövde's startup program — from application to exit, managing over 200 startups.","md",true,{},1,"\u002Fportfolio\u002Fen\u002Fsia",{"title":6,"description":168},"portfolio\u002Fen\u002Fsia",[177,178,179,180,181],".net","vue","typescript","signalr","sql-server","h-QDY8f4Y436hKaw8e--E3hXvLCQRHxLh6kocHjKl4M",{"id":184,"title":185,"body":186,"client":371,"date":372,"description":373,"extension":169,"featured":170,"meta":374,"navigation":170,"order":159,"path":375,"seo":376,"stem":377,"tags":378,"thumbnail":333,"__hash__":382},"portfolio_en\u002Fportfolio\u002Fen\u002Fbizscree.md","Bizscree — Platform for startups and aggregators",{"type":8,"value":187,"toc":364},[188,190,193,196,198,272,274,277,326,328,334,340,346,348,353,358],[11,189,14],{"id":13},[16,191,192],{},"Bizscree replaces the fragmented reporting where startups have to duplicate their data for every investor, incubator, or accelerator they work with. Instead, companies create a single comprehensive profile — financials, team, projects, KPIs — and grant each aggregator exactly the level of access they need.",[16,194,195],{},"\"Build once, share many\" — a single source of truth per company, with granular control over who sees what.",[11,197,25],{"id":24},[27,199,200,206,212,218,224,230,236,242,248,254,260,266],{},[30,201,202,205],{},[33,203,204],{},"Company profiles"," — Financials, team, projects, business plan, and data rooms all in one place",[30,207,208,211],{},[33,209,210],{},"Portfolio management"," — Aggregators get granular permission controls over their portfolio companies",[30,213,214,217],{},[33,215,216],{},"Virtual companies"," — Aggregators can create profiles for companies not yet on the platform; real companies can later claim and take them over",[30,219,220,223],{},[33,221,222],{},"KPI tracking"," — Custom metrics, targets, and trend analysis per portfolio company",[30,225,226,229],{},[33,227,228],{},"Portfolio analytics"," — Sector breakdown, stage distribution, and performance reports",[30,231,232,235],{},[33,233,234],{},"CEO reports"," — Structured updates and progress boards",[30,237,238,241],{},[33,239,240],{},"Passwordless auth"," — Magic-link sign-in with multi-organization support",[30,243,244,247],{},[33,245,246],{},"Real-time notifications"," — WebSocket delivery via SignalR",[30,249,250,253],{},[33,251,252],{},"AI-powered features"," — CEO briefs and suggestions via OpenAI",[30,255,256,259],{},[33,257,258],{},"PDF export"," — Reports and profiles as downloadable PDFs",[30,261,262,265],{},[33,263,264],{},"Audit logs"," — Full traceability for compliance",[30,267,268,271],{},[33,269,270],{},"Guided onboarding wizards"," — For both company and aggregator organizations",[11,273,82],{"id":81},[16,275,276],{},"Bizscree is built as a clean SPA + API architecture with full separation between frontend and backend:",[27,278,279,285,291,297,303,314,320],{},[30,280,281,284],{},[33,282,283],{},"End-to-end type safety"," — Auto-generated TypeScript client from the OpenAPI spec via hey-api",[30,286,287,290],{},[33,288,289],{},"Organization-aware authorization"," — Middleware extracts organization context; policies and handlers scope access per aggregator",[30,292,293,296],{},[33,294,295],{},"Real-time updates"," — SignalR hubs push notifications straight into the UI",[30,298,299,302],{},[33,300,301],{},"Rate limiting"," — Fixed-window policies protect sensitive endpoints (auth, AI, uploads)",[30,304,305,308,309,313],{},[33,306,307],{},"Health checks"," — ",[310,311,312],"code",{},"\u002Fhealth"," endpoint for load balancers and monitoring",[30,315,316,319],{},[33,317,318],{},"Structured logging"," — Serilog with rolling files in production",[30,321,322,325],{},[33,323,324],{},"Production-hardened"," — Ten implementation phases delivered: security, infrastructure, deployment, features, polish, notifications, analytics and KPIs",[11,327,115],{"id":114},[16,329,330],{},[119,331],{"alt":332,"src":333},"Bizscree dashboard — portfolio overview with companies, projects, CEO reports and charts for acquisitions, countries and gender distribution","\u002Fimages\u002Fportfolio\u002Fbizscree-dashboard.png",[16,335,336],{},[119,337],{"alt":338,"src":339},"Progress Board — portfolio status per company with traffic-light indicators for production, publishing, finance and compliance","\u002Fimages\u002Fportfolio\u002Fbizscree-portfolio.png",[16,341,342],{},[119,343],{"alt":344,"src":345},"Company management — list of portfolio companies with type, acquisition date, country and active status","\u002Fimages\u002Fportfolio\u002Fbizscree-companies.png",[11,347,144],{"id":143},[16,349,350,352],{},[33,351,149],{}," Vue 3, TypeScript, PrimeVue 4, Tailwind CSS 4, Pinia, hey-api (OpenAPI client generation)",[16,354,355,357],{},[33,356,155],{}," ASP.NET Core 10, C#, Entity Framework Core 10, PostgreSQL, SignalR, Serilog, QuestPDF, OpenAI",[16,359,360,363],{},[33,361,362],{},"Infrastructure:"," Hetzner Object Storage (S3-compatible), cookie-based passwordless auth",{"title":158,"searchDepth":159,"depth":159,"links":365},[366,367,368,369,370],{"id":13,"depth":159,"text":14},{"id":24,"depth":159,"text":25},{"id":81,"depth":159,"text":82},{"id":114,"depth":159,"text":115},{"id":143,"depth":159,"text":144},"Bizscree AB","2023-10-01","Platform connecting startups with incubators, investors and accelerators — one profile, many sharing levels.",{},"\u002Fportfolio\u002Fen\u002Fbizscree",{"title":185,"description":373},"portfolio\u002Fen\u002Fbizscree",[177,178,179,379,180,380,381],"postgresql","ai","saas","K70j6dwBP9Hl6vxdiRq91serxJSsw9fx8k3Qr4XLK4s",{"id":384,"title":385,"body":386,"client":514,"date":515,"description":516,"extension":169,"featured":170,"meta":517,"navigation":170,"order":518,"path":519,"seo":520,"stem":521,"tags":522,"thumbnail":524,"__hash__":525},"portfolio_en\u002Fportfolio\u002Fen\u002Fvensire.md","Vensire — The identifier of growth companies",{"type":8,"value":387,"toc":508},[388,390,393,396,399,401,457,459,465,471,473,481,486,496,502],[11,389,14],{"id":13},[16,391,392],{},"Vensire is a multi-tenant SaaS platform that helps regional business-development professionals identify Swedish growth companies with the greatest potential to create future jobs. Instead of reactive development — responding to news and tips — users get a data-driven radar over the companies in their region.",[16,394,395],{},"At the core is a proprietary classification algorithm that analyzes multi-year time series of revenue (Mkr) and employee count, inflation-adjusted and annualized, placing each company into one of five categories: revitalized, weakly revitalized, constantly growing, stable, or unclassified. On top of the classification it computes a 1–5 growth rating, a 0–9 profitability level, and surfaces patterns like synchronized extreme growth — signals that may indicate mergers or acquisitions.",[16,397,398],{},"We built the whole system — the classification algorithm, the backend API, and the Vue SPA. We also built the marketing site vensire.se in WordPress, and we handle hosting and operations for the application ourselves.",[11,400,25],{"id":24},[27,402,403,409,415,421,427,433,439,445,451],{},[30,404,405,408],{},[33,406,407],{},"Tillväxtradarn (Growth Radar)"," — The core feature: lists all revitalized, constantly growing, and stable companies by municipality, industry, and size",[30,410,411,414],{},[33,412,413],{},"Classification algorithm"," — Ten-step pipeline that identifies stable periods, revitalization periods, and constant growth in company histories",[30,416,417,420],{},[33,418,419],{},"Growth rating & profitability"," — Composite 1–5 growth rating and 0–9 profitability level",[30,422,423,426],{},[33,424,425],{},"Company details"," — Interactive timeline charts showing revenue and employees per year, with color-coded periods (green for revitalization, yellow for stable phases)",[30,428,429,432],{},[33,430,431],{},"Filters & export"," — Filtering by municipality, industry (SNI code), company size, and revitalization period, with Excel export",[30,434,435,438],{},[33,436,437],{},"Company tracking"," — Notifications when companies change CEO or enter new classification states",[30,440,441,444],{},[33,442,443],{},"Comparison view"," — Compare multiple companies side by side",[30,446,447,450],{},[33,448,449],{},"Multi-tenant"," — Role-based access with organizations: Admin, OrganizationAdmin, OrganizationUser",[30,452,453,456],{},[33,454,455],{},"External data import"," — Batch importer for Retriever, Bisnode, SNI, group\u002Fownership data, and more",[11,458,115],{"id":114},[16,460,461],{},[119,462],{"alt":463,"src":464},"Revitalized companies — list view with filtering by municipality, industry, and size, showing growth and profitability ratings","\u002Fimages\u002Fportfolio\u002Fvensire-list.png",[16,466,467],{},[119,468],{"alt":469,"src":470},"Company detail — A Society AB with timeline chart showing revitalization period (green) and stable phase (yellow) across 2004–2021","\u002Fimages\u002Fportfolio\u002Fvensire-detail.png",[11,472,144],{"id":143},[16,474,475,477,478],{},[33,476,149],{}," Vue 3.4, TypeScript, Vite 5, Pinia, Tailwind CSS 3.4, HeadlessUI, ApexCharts, vee-validate, ",[310,479,480],{},"@microsoft\u002Fsignalr",[16,482,483,485],{},[33,484,155],{}," ASP.NET Core 8, C#, Entity Framework Core 8, PostgreSQL, ASP.NET Identity (cookie auth), AutoMapper, SignalR, Swashbuckle\u002FOpenAPI",[16,487,488,491,492,495],{},[33,489,490],{},"Algorithm library:"," Pure .NET 8 class library (only external dependency is ",[310,493,494],{},"OneOf",")",[16,497,498,501],{},[33,499,500],{},"Secondary UI:"," Blazor WebAssembly for algorithm result comparison and manual QA",[16,503,504,507],{},[33,505,506],{},"CI\u002FCD:"," GitHub Actions → SCP → systemd on bare-metal",{"title":158,"searchDepth":159,"depth":159,"links":509},[510,511,512,513],{"id":13,"depth":159,"text":14},{"id":24,"depth":159,"text":25},{"id":114,"depth":159,"text":115},{"id":143,"depth":159,"text":144},"Vensire AB","2022-01-01","Multi-tenant SaaS for regional business development — classifies Swedish companies by growth and stability using a proprietary algorithm.",{},3,"\u002Fportfolio\u002Fen\u002Fvensire",{"title":385,"description":516},"portfolio\u002Fen\u002Fvensire",[177,178,179,379,180,381,523],"analytics","\u002Fimages\u002Fportfolio\u002Fvensire-hero.png","IxkMHqSOCFskMhYU_MUvF3nrYKl4aH3szpOy8foEos4",{"id":527,"title":528,"body":529,"client":587,"date":588,"description":589,"extension":169,"featured":170,"meta":590,"navigation":170,"order":591,"path":592,"seo":593,"stem":594,"tags":595,"thumbnail":599,"__hash__":600},"portfolio_en\u002Fportfolio\u002Fen\u002Fmillion-games.md","Million Games — Studio Management & Development",{"type":8,"value":530,"toc":582},[531,533,536,540,566,568],[11,532,14],{"id":13},[16,534,535],{},"Xenolith AB has provided studio management to Million Games AB since 2023, overseeing the development and lifecycle management of iGaming products.",[11,537,539],{"id":538},"what-we-delivered","What we delivered",[27,541,542,548,554,560],{},[30,543,544,547],{},[33,545,546],{},"Studio Management"," — Overall responsibility for a team of approximately 15 people",[30,549,550,553],{},[33,551,552],{},"Product Development"," — Slots, crash games, and arcade-style casino titles",[30,555,556,559],{},[33,557,558],{},"Technical Architecture"," — Established development processes and technical stack",[30,561,562,565],{},[33,563,564],{},"Quality Assurance"," — Implemented testing strategies and CI\u002FCD workflows",[11,567,144],{"id":143},[27,569,570,573,576,579],{},[30,571,572],{},".NET \u002F C#",[30,574,575],{},"TypeScript",[30,577,578],{},"PixiJS",[30,580,581],{},"Azure",{"title":158,"searchDepth":159,"depth":159,"links":583},[584,585,586],{"id":13,"depth":159,"text":14},{"id":538,"depth":159,"text":539},{"id":143,"depth":159,"text":144},"Million Games AB","2023-01-01","Hands-on technical leadership and development of iGaming products including slots, crash games, and arcade titles.",{},4,"\u002Fportfolio\u002Fen\u002Fmillion-games",{"title":528,"description":589},"portfolio\u002Fen\u002Fmillion-games",[596,177,179,597,598],"igaming","pixijs","management","\u002Fimages\u002Fportfolio\u002Fmillion-games-logo.png","Md39deFMbYvZXWnBj3N8hpjK8e5xuqGeY7qN6LCPs-s",{"id":602,"title":603,"body":604,"client":587,"date":711,"description":712,"extension":169,"featured":170,"meta":713,"navigation":170,"order":714,"path":715,"seo":716,"stem":717,"tags":718,"thumbnail":679,"__hash__":719},"portfolio_en\u002Fportfolio\u002Fen\u002Fchicken-x-competition.md","Chicken X and Friends — Trade-show competition platform",{"type":8,"value":605,"toc":704},[606,608,611,613,657,661,672,674,680,686,688,693,698],[11,607,14],{"id":13},[16,609,610],{},"For trade shows, Million Games wanted a competition station where visitors could play Chicken X and Friends for 15 minutes and chase the top of the leaderboard. We built the whole competition system — registration form, game-session handling, live leaderboard, and admin panel — capturing participant scores and contact details for prize draws and marketing follow-up.",[11,612,25],{"id":24},[27,614,615,621,627,633,639,645,651],{},[30,616,617,620],{},[33,618,619],{},"Registration"," — Name, company, email with built-in validation and a GDPR marketing opt-in",[30,622,623,626],{},[33,624,625],{},"Game integration"," — Automatically creates game sessions via Million Games' launcher API",[30,628,629,632],{},[33,630,631],{},"Score tracking"," — Background polling fetches results directly from the game's API",[30,634,635,638],{},[33,636,637],{},"Live leaderboard"," — Real-time rankings with pagination and auto-refresh",[30,640,641,644],{},[33,642,643],{},"Duplicate prevention"," — The same email redirects to an active session instead of creating a new one",[30,646,647,650],{},[33,648,649],{},"Admin panel"," — Password-protected view to manage, sort, edit, and delete entries",[30,652,653,656],{},[33,654,655],{},"Self-contained build"," — A single .NET binary serves both the API and the frontend, trivial to deploy on a show-floor laptop",[11,658,660],{"id":659},"competition-rules","Competition rules",[27,662,663,666,669],{},[30,664,665],{},"15 minutes to compete",[30,667,668],{},"Last 10 rounds count toward your score",[30,670,671],{},"Highest score wins!",[11,673,115],{"id":114},[16,675,676],{},[119,677],{"alt":678,"src":679},"Registration page with the Million Games logo, the Chicken X and Friends title, and a form for name, company, email and a GDPR marketing opt-in — on a top-down in-game background","\u002Fimages\u002Fportfolio\u002Fchicken-x-competition-register.png",[16,681,682],{},[119,683],{"alt":684,"src":685},"Live leaderboard showing top-ranked players, companies and scores over the same in-game background as the registration page","\u002Fimages\u002Fportfolio\u002Fchicken-x-competition-leaderboard.png",[11,687,144],{"id":143},[16,689,690,692],{},[33,691,149],{}," Vue 3, TypeScript, Nuxt UI 4, Tailwind CSS 4, Vite, Valibot",[16,694,695,697],{},[33,696,155],{}," .NET 9, C#, Entity Framework Core, SQLite",[16,699,700,703],{},[33,701,702],{},"Deploy:"," Self-contained .NET binary — no external database or runtime required on the show-floor laptop",{"title":158,"searchDepth":159,"depth":159,"links":705},[706,707,708,709,710],{"id":13,"depth":159,"text":14},{"id":24,"depth":159,"text":25},{"id":659,"depth":159,"text":660},{"id":114,"depth":159,"text":115},{"id":143,"depth":159,"text":144},"2025-11-01","Trade-show competition for the Million Games title Chicken X and Friends — registration, live leaderboard and admin panel in a single self-contained build.",{},5,"\u002Fportfolio\u002Fen\u002Fchicken-x-competition",{"title":603,"description":712},"portfolio\u002Fen\u002Fchicken-x-competition",[178,179,177,596],"7PS0mvP6M4dtjVS8a4Hb3yaOquTjnBqKI315iN0mtG0",{"id":721,"title":722,"body":723,"client":852,"date":853,"description":854,"extension":169,"featured":170,"meta":855,"navigation":170,"order":856,"path":857,"seo":858,"stem":859,"tags":860,"thumbnail":862,"__hash__":863},"portfolio_en\u002Fportfolio\u002Fen\u002Ftranslator-tool.md","TranslatorTool — AI-driven iGaming localization",{"type":8,"value":724,"toc":846},[725,727,730,733,735,800,804,830,832],[11,726,14],{"id":13},[16,728,729],{},"TranslatorTool is an internal tool we built to automate localization of iGaming content. Given a set of English source files (JSON or TXT), the tool translates the content into up to 37 languages via the OpenAI Responses API, with built-in quality assurance, translation memory, and an industry-tuned terminology glossary that keeps jackpot, scatter and similar terms consistent across entire game libraries.",[16,731,732],{},"It runs locally through an interactive menu — pick languages, adjust reasoning effort (low\u002Fmedium\u002Fhigh), set the parallelism level, and choose whether to run QA validation — and the output lands in a folder ready to be dropped into the client's game.",[11,734,25],{"id":24},[27,736,737,743,749,755,761,767,773,779],{},[30,738,739,742],{},[33,740,741],{},"37 languages"," — Coverage for global casino operations, from Swedish and Spanish to Bulgarian and Japanese",[30,744,745,748],{},[33,746,747],{},"Multi-format"," — Handles both JSON and TXT files with intelligent structure preservation",[30,750,751,754],{},[33,752,753],{},"Parallel processing"," — Translates multiple files and languages concurrently (5–10x faster than sequential)",[30,756,757,760],{},[33,758,759],{},"Translation memory"," — Reuses past translations at 85%+ similarity, keeping terminology consistent and cutting API costs",[30,762,763,766],{},[33,764,765],{},"Quality assurance"," — Structured AI-powered QA with 0–100 scoring, severity classification (critical\u002Fmajor\u002Fminor) and automatic retries with feedback",[30,768,769,772],{},[33,770,771],{},"Terminology glossary"," — Built-in iGaming glossary with preferred translations for industry terms",[30,774,775,778],{},[33,776,777],{},"Smart recovery"," — Resumes interrupted sessions via file-hash-based translation history",[30,780,781,784,785,788,789,788,792,795,796,799],{},[33,782,783],{},"Placeholder safety"," — Correctly preserves variables like ",[310,786,787],{},"{{VARIABLE}}",", ",[310,790,791],{},"::VARIABLE::",[310,793,794],{},"%s","\u002F",[310,797,798],{},"%d",", HTML tags and attributes",[11,801,803],{"id":802},"igaming-specific-touches","iGaming-specific touches",[27,805,806,812,818,824],{},[30,807,808,811],{},[33,809,810],{},"Social casino mode"," — A special variant (\"ex\" — English Social) that automatically swaps gambling terminology for social-casino-friendly words: balance → coins, bet → play\u002Fspin, payout → win",[30,813,814,817],{},[33,815,816],{},"Regulatory considerations"," — Separate term and tone handling for different regulated markets",[30,819,820,823],{},[33,821,822],{},"UI constraints"," — Respects max-length budgets for button text and tooltip space",[30,825,826,829],{},[33,827,828],{},"Industry terms"," — Consistent translation of free spins, wild, scatter, multiplier and the like across full deliveries",[11,831,144],{"id":143},[27,833,834,837,840,843],{},[30,835,836],{},".NET 9 \u002F C#",[30,838,839],{},"OpenAI Responses API (GPT-5.2)",[30,841,842],{},"Interactive console menu",[30,844,845],{},"Runs locally — no server or database dependencies",{"title":158,"searchDepth":159,"depth":159,"links":847},[848,849,850,851],{"id":13,"depth":159,"text":14},{"id":24,"depth":159,"text":25},{"id":802,"depth":159,"text":803},{"id":143,"depth":159,"text":144},"Xenolith AB (in-house tool)","2025-06-01","Internal tool for automated localization of iGaming content into 37 languages via the OpenAI Responses API — with translation memory and quality assurance.",{},6,"\u002Fportfolio\u002Fen\u002Ftranslator-tool",{"title":722,"description":854},"portfolio\u002Fen\u002Ftranslator-tool",[177,380,596,861],"localization","\u002Fimages\u002Fportfolio\u002Ftranslator-tool-hero.jpg","4ylDZ9ScQKrNi18JIXCqH2kVAaVWtM0blCDOF2y6gS0",{"id":865,"title":866,"body":867,"client":993,"date":994,"description":995,"extension":169,"featured":170,"meta":996,"navigation":170,"order":997,"path":998,"seo":999,"stem":1000,"tags":1001,"thumbnail":955,"__hash__":1003},"portfolio_en\u002Fportfolio\u002Fen\u002Fvision-backoffice.md","Vision Backoffice — Control center for iGaming operators",{"type":8,"value":868,"toc":986},[869,871,874,877,879,917,919,922,948,950,956,962,968,974,976,981],[11,870,14],{"id":13},[16,872,873],{},"Vision Backoffice (VBO) is the administrative control center bundled with Reelsoft's Vision products (Vision RGS and Vision Link). The platform gives online-casino operators full visibility and control over their gaming operations — from real-time dashboards and deep analytics to custom reports and configuration of games, operators, and providers.",[16,875,876],{},"We built the whole system — the frontend SPA and the Java API powering it — for Reelsoft.",[11,878,25],{"id":24},[27,880,881,887,893,899,905,911],{},[30,882,883,886],{},[33,884,885],{},"Dashboard"," — Real-time overview with day\u002Fmonth\u002Fprevious-period comparisons: players, rounds, wagers, winnings, GGR and RTP",[30,888,889,892],{},[33,890,891],{},"Charts & analytics"," — 30-day trend graphs per metric, filterable by operator",[30,894,895,898],{},[33,896,897],{},"Custom reports"," — Performance reports segmented by operator, provider, game, brand, and country",[30,900,901,904],{},[33,902,903],{},"Configuration"," — Manage games, operators, providers, currencies, RTP versions, and market settings",[30,906,907,910],{},[33,908,909],{},"Administration"," — Role-based access, user management, and system settings",[30,912,913,916],{},[33,914,915],{},"Global search"," — Instant lookup across players, rounds, and transaction IDs",[11,918,82],{"id":81},[16,920,921],{},"VBO is built as a clean SPA + API architecture with strict separation between frontend and backend:",[27,923,924,930,936,942],{},[30,925,926,929],{},[33,927,928],{},"Modular Vue 3 frontend"," — Component-based architecture with full light\u002Fdark mode support",[30,931,932,935],{},[33,933,934],{},"Java REST API"," — Backend designed to handle high volumes of gaming transactions",[30,937,938,941],{},[33,939,940],{},"Operator-aware filtering"," — All data can be sliced per operator for multi-tenant scenarios",[30,943,944,947],{},[33,945,946],{},"Near-real-time dashboards"," — Fast aggregations for daily and monthly KPIs",[11,949,115],{"id":114},[16,951,952],{},[119,953],{"alt":954,"src":955},"Vision Backoffice dashboard — players, rounds, wagers, GGR and RTP across day, month and previous period","\u002Fimages\u002Fportfolio\u002Fvision-backoffice-dashboard.png",[16,957,958],{},[119,959],{"alt":960,"src":961},"30-day trend charts for wagers, winnings, GGR, players, rounds and RTP","\u002Fimages\u002Fportfolio\u002Fvision-backoffice-charts.png",[16,963,964],{},[119,965],{"alt":966,"src":967},"Operator configuration — list of operators with RTP version, market controls and buy-feature settings","\u002Fimages\u002Fportfolio\u002Fvision-backoffice-config.png",[16,969,970],{},[119,971],{"alt":972,"src":973},"Performance report segmented by provider with detailed KPIs","\u002Fimages\u002Fportfolio\u002Fvision-backoffice-reports.png",[11,975,144],{"id":143},[16,977,978,980],{},[33,979,149],{}," Vue 3, TypeScript, Pinia, Vite",[16,982,983,985],{},[33,984,155],{}," Java, REST API",{"title":158,"searchDepth":159,"depth":159,"links":987},[988,989,990,991,992],{"id":13,"depth":159,"text":14},{"id":24,"depth":159,"text":25},{"id":81,"depth":159,"text":82},{"id":114,"depth":159,"text":115},{"id":143,"depth":159,"text":144},"Reelsoft (Vision RGS)","2024-03-01","Administrative control panel for Reelsoft's Vision iGaming platform — dashboards, analytics, custom reports and operator configuration.",{},7,"\u002Fportfolio\u002Fen\u002Fvision-backoffice",{"title":866,"description":995},"portfolio\u002Fen\u002Fvision-backoffice",[178,179,1002,596,381,598],"java","8UX5YqEGmr7Cmvt6yPnqmPiom8E4OjAqRejlk8VSNdQ",{"id":1005,"title":1006,"body":1007,"client":1107,"date":515,"description":1108,"extension":169,"featured":170,"meta":1109,"navigation":170,"order":1110,"path":1111,"seo":1112,"stem":1113,"tags":1114,"thumbnail":1077,"__hash__":1116},"portfolio_en\u002Fportfolio\u002Fen\u002Finflyttarservice.md","Inflyttarservice — Case Management for Municipalities",{"type":8,"value":1008,"toc":1101},[1009,1011,1014,1016,1064,1066,1072,1078,1083,1085,1090,1095],[11,1010,14],{"id":13},[16,1012,1013],{},"Inflyttarservice is a case management platform built for Skaraborgs Kommunalförbund. The system helps agents track applicants from initial registration through to successful settlement, with municipality-scoped access control, automated workflows, and a public-facing application portal.",[11,1015,25],{"id":24},[27,1017,1018,1024,1030,1035,1041,1047,1053,1059],{},[30,1019,1020,1023],{},[33,1021,1022],{},"Applicant lifecycle management"," — Track cases through New, Claimed, Success, Inactive, and Aborted statuses with agent assignment, file uploads, comments, and linked applicants",[30,1025,1026,1029],{},[33,1027,1028],{},"Public application portal"," — Embeddable, municipality-specific forms with configurable field visibility",[30,1031,1032,1034],{},[33,1033,885],{}," — Real-time applicant counts, recent activity feed, and historical trend charts",[30,1036,1037,1040],{},[33,1038,1039],{},"Reports and export"," — Filter by municipality, status, date range, and more; export to Excel",[30,1042,1043,1046],{},[33,1044,1045],{},"Role-based access control"," — Four roles (Superadmin, Teamlead, Agent, Applicant) with municipality-scoped data isolation",[30,1048,1049,1052],{},[33,1050,1051],{},"Dynamic form builder"," — Customize public-facing forms, toggle fields, set defaults, and copy embed code",[30,1054,1055,1058],{},[33,1056,1057],{},"Background automation"," — Hangfire jobs handle inactivity detection, file cleanup, and scheduled reminders",[30,1060,1061,1063],{},[33,1062,246],{}," — SignalR push notifications and email alerts for assignments, comments, and status changes",[11,1065,115],{"id":114},[16,1067,1068],{},[119,1069],{"alt":1070,"src":1071},"Inflyttarservice login","\u002Fimages\u002Fportfolio\u002Finflyttarservice-login.jpg",[16,1073,1074],{},[119,1075],{"alt":1076,"src":1077},"Inflyttarservice Dashboard","\u002Fimages\u002Fportfolio\u002Finflyttarservice-dashboard.png",[16,1079,1080],{},[119,1081],{"alt":1051,"src":1082},"\u002Fimages\u002Fportfolio\u002Finflyttarservice-forms.png",[11,1084,144],{"id":143},[16,1086,1087,1089],{},[33,1088,155],{}," ASP.NET Core, C#, Entity Framework Core, PostgreSQL, Hangfire, SignalR",[16,1091,1092,1094],{},[33,1093,149],{}," Vue 2.7, Tailwind CSS, Axios",[16,1096,1097,1100],{},[33,1098,1099],{},"Other:"," MailKit (SMTP), ClosedXML (Excel), GitHub Actions CI\u002FCD",{"title":158,"searchDepth":159,"depth":159,"links":1102},[1103,1104,1105,1106],{"id":13,"depth":159,"text":14},{"id":24,"depth":159,"text":25},{"id":114,"depth":159,"text":115},{"id":143,"depth":159,"text":144},"Skaraborgs Kommunalförbund","Case management platform for Swedish municipalities supporting people relocating to the area — with lifecycle management, automated workflows, and a public application portal.",{},8,"\u002Fportfolio\u002Fen\u002Finflyttarservice",{"title":1006,"description":1108},"portfolio\u002Fen\u002Finflyttarservice",[177,178,379,180,1115],"hangfire","9FDK2N67-d7UDjbYO2MZrJzFlp4WMLIhkK3Q0A89vAE",{"id":1118,"title":1119,"body":1120,"client":1222,"date":1223,"description":1224,"extension":169,"featured":170,"meta":1225,"navigation":170,"order":1226,"path":1227,"seo":1228,"stem":1229,"tags":1230,"thumbnail":1191,"__hash__":1233},"portfolio_en\u002Fportfolio\u002Fen\u002Fsiguru.md","Siguru — Gamified Cybersecurity Training",{"type":8,"value":1121,"toc":1216},[1122,1124,1127,1130,1134,1184,1186,1192,1198,1204,1206,1211],[11,1123,14],{"id":13},[16,1125,1126],{},"Siguru is a gamified cybersecurity awareness platform that makes learning about security engaging and effective. Through interactive cards and game mechanics, users learn about common cyber threats in a memorable way.",[16,1128,1129],{},"The platform includes over 127 pre-populated cards — 102 term cards covering cybersecurity education across three difficulty levels, and 25 action cards with game mechanics. All content is expert-reviewed and available in English, Swedish, and German.",[11,1131,1133],{"id":1132},"features","Features",[27,1135,1136,1142,1148,1154,1160,1166,1172,1178],{},[30,1137,1138,1141],{},[33,1139,1140],{},"Interactive term cards"," — Cybersecurity content across three difficulty levels with attack pathways and protection methods",[30,1143,1144,1147],{},[33,1145,1146],{},"Action cards"," — Game mechanics that simulate real-world scenarios (Before, Defense, During)",[30,1149,1150,1153],{},[33,1151,1152],{},"Organization tracking"," — Unique 2-character codes per organization, real-time dashboard with live activity feeds, statistics by language and category, CSV export",[30,1155,1156,1159],{},[33,1157,1158],{},"GDPR-compliant"," — All data collection is anonymized",[30,1161,1162,1165],{},[33,1163,1164],{},"Multilingual support"," — English, Swedish, and German with AI-powered translations and expert review",[30,1167,1168,1171],{},[33,1169,1170],{},"QR codes"," — Scan a card, enter your organization code, and start learning — simple onboarding",[30,1173,1174,1177],{},[33,1175,1176],{},"Dashboard with analytics"," — Real-time view of page views, top cards, and activity by language",[30,1179,1180,1183],{},[33,1181,1182],{},"Multimedia"," — Support for text, audio, and video in every card",[11,1185,115],{"id":114},[16,1187,1188],{},[119,1189],{"alt":1190,"src":1191},"Siguru Dashboard — analytics and top cards","\u002Fimages\u002Fportfolio\u002Fsiguru-dashboard.png",[16,1193,1194],{},[119,1195],{"alt":1196,"src":1197},"Card library with filtering","\u002Fimages\u002Fportfolio\u002Fsiguru-cards.png",[16,1199,1200],{},[119,1201],{"alt":1202,"src":1203},"Admin panel with QR codes and card links","\u002Fimages\u002Fportfolio\u002Fsiguru-admin.png",[11,1205,144],{"id":143},[16,1207,1208,1210],{},[33,1209,149],{}," Vue 3, TypeScript, Tailwind CSS 4, Pinia, Vite",[16,1212,1213,1215],{},[33,1214,155],{}," ASP.NET Core 9.0, C#, Entity Framework Core, SQLite, Swagger\u002FOpenAPI",{"title":158,"searchDepth":159,"depth":159,"links":1217},[1218,1219,1220,1221],{"id":13,"depth":159,"text":14},{"id":1132,"depth":159,"text":1133},{"id":114,"depth":159,"text":115},{"id":143,"depth":159,"text":144},"Siguru (in-house project with University of Skovde)","2024-01-01","A gamified training platform that teaches organizations about cybersecurity through interactive cards, multilingual content, and game mechanics.",{},9,"\u002Fportfolio\u002Fen\u002Fsiguru",{"title":1119,"description":1224},"portfolio\u002Fen\u002Fsiguru",[177,178,179,1231,1232],"cybersecurity","gamification","-Svu3okVzSok_b5idsnuiO2XWlpvSCypDP-0Er6vBIw",{"id":1235,"title":1236,"body":1237,"client":1358,"date":1359,"description":1360,"extension":169,"featured":170,"meta":1361,"navigation":170,"order":1362,"path":1363,"seo":1364,"stem":1365,"tags":1366,"thumbnail":1368,"__hash__":1369},"portfolio_en\u002Fportfolio\u002Fen\u002Fiodesk.md","IOdesk — All-In-One Customer Support",{"type":8,"value":1238,"toc":1350},[1239,1241,1244,1247,1251,1254,1257,1259,1297,1301,1304,1313,1316,1318,1324,1330,1336,1338],[11,1240,14],{"id":13},[16,1242,1243],{},"IOdesk is Xenolith AB's own SaaS product — an all-in-one customer support platform powered by AI. Create knowledge bases, use self-service tools to guide your users when they're stuck, chat in real-time, and manage email support — all from one place.",[16,1245,1246],{},"The goal: reduce the support load for your team and provide a better experience for your users.",[11,1248,1250],{"id":1249},"lydia-ai-powered-self-service","Lydia — AI-Powered Self-Service",[16,1252,1253],{},"IOdesk's built-in AI agent Lydia helps customers help themselves. She analyzes questions, provides answers based on earlier customer interactions, and handles repetitive inquiries automatically — in the customer's own language, whether that's English, Swedish, or anything else.",[16,1255,1256],{},"Three out of four people prefer to solve issues on their own. Lydia makes that possible.",[11,1258,1133],{"id":1132},[27,1260,1261,1267,1273,1279,1285,1291],{},[30,1262,1263,1266],{},[33,1264,1265],{},"Knowledge Base"," — Create guides and articles so users can find answers on their own",[30,1268,1269,1272],{},[33,1270,1271],{},"Live Chat with Self-Service"," — One line of code to add the chat to your site. Lydia helps the customer directly or pins down the problem before you take over",[30,1274,1275,1278],{},[33,1276,1277],{},"Shared Mail Inbox"," — Gather all incoming customer emails in one place",[30,1280,1281,1284],{},[33,1282,1283],{},"Ticket Management"," — Structured handling of support cases via email and forms",[30,1286,1287,1290],{},[33,1288,1289],{},"Contact Forms & FAQ Widgets"," — Embedded tools for your websites",[30,1292,1293,1296],{},[33,1294,1295],{},"Multilingual AI"," — Automatic help regardless of the customer's language",[11,1298,1300],{"id":1299},"case-study-graphic-powers-ab","Case Study: Graphic Powers AB",[16,1302,1303],{},"Graphic Powers AB, a Swedish software company with customers across all time zones, needed a support system able to answer questions 24\u002F7.",[1305,1306,1307],"blockquote",{},[16,1308,1309,1310],{},"\"IOdesk's built-in AI agent Lydia helps our customers quickly find the answer to frequently asked questions, without us having to take any action. IOdesk helps us daily by gathering all support tickets in one system, and handling a good portion of it automatically.\" — ",[33,1311,1312],{},"Mats Löfberg, CEO",[16,1314,1315],{},"Thanks to Lydia always being available, customer satisfaction has increased — both because customers get answers instantly, and because the team now has more time for answering complicated questions more thoroughly.",[11,1317,115],{"id":114},[16,1319,1320],{},[119,1321],{"alt":1322,"src":1323},"IOdesk Dashboard","\u002Fimages\u002Fportfolio\u002Fiodesk-dashboard.jpg",[16,1325,1326],{},[119,1327],{"alt":1328,"src":1329},"IOdesk Chat with Lydia AI","\u002Fimages\u002Fportfolio\u002Fiodesk-chat.jpg",[16,1331,1332],{},[119,1333],{"alt":1334,"src":1335},"IOdesk Shared Inbox","\u002Fimages\u002Fportfolio\u002Fiodesk-inbox.png",[11,1337,144],{"id":143},[27,1339,1340,1343,1345,1347],{},[30,1341,1342],{},"Vue.js",[30,1344,572],{},[30,1346,581],{},[30,1348,1349],{},"AI\u002FML models (NLP, multilingual)",{"title":158,"searchDepth":159,"depth":159,"links":1351},[1352,1353,1354,1355,1356,1357],{"id":13,"depth":159,"text":14},{"id":1249,"depth":159,"text":1250},{"id":1132,"depth":159,"text":1133},{"id":1299,"depth":159,"text":1300},{"id":114,"depth":159,"text":115},{"id":143,"depth":159,"text":144},"Xenolith AB (in-house)","2019-06-01","All-in-one customer support platform that reduces the support load for your team and provides a better experience for your users.",{},10,"\u002Fportfolio\u002Fen\u002Fiodesk",{"title":1236,"description":1360},"portfolio\u002Fen\u002Fiodesk",[381,178,380,177,1367],"azure","\u002Fimages\u002Fportfolio\u002Fiodesk-cover.jpg","2nEZ2US0hE7rabOIhNqEz1cwiGmGmrdp-bh_Wo1O3uw",{"id":1371,"title":1372,"body":1373,"client":1430,"date":1431,"description":1432,"extension":169,"featured":170,"meta":1433,"navigation":170,"order":1434,"path":1435,"seo":1436,"stem":1437,"tags":1438,"thumbnail":1441,"__hash__":1442},"portfolio_en\u002Fportfolio\u002Fen\u002Fgraphic-powers.md","Graphic Powers — Website, Administration & Licensing",{"type":8,"value":1374,"toc":1421},[1375,1377,1380,1383,1385,1390,1393,1397,1400,1404,1407,1409],[11,1376,14],{"id":13},[16,1378,1379],{},"Graphic Powers AB is a Swedish software company developing vector graphics tools for graphic professionals, sign makers, engravers, and print shops worldwide. Their flagship product Graphic Tracer converts low-resolution images into scalable vector graphics using proprietary technology like SensEdge and FontEye.",[16,1381,1382],{},"Xenolith AB has built and maintains three core systems for Graphic Powers:",[11,1384,539],{"id":538},[1386,1387,1389],"h3",{"id":1388},"website-store-graphicpowerscom","Website & store — graphicpowers.com",[16,1391,1392],{},"The public-facing website with an integrated store for Graphic Tracer. Customers can purchase licenses, subscribe, and manage their accounts — all connected to Stripe for seamless payment handling with support for monthly subscriptions, annual plans, and lifetime licenses.",[1386,1394,1396],{"id":1395},"web-based-administration-system","Web-based administration system",[16,1398,1399],{},"Administration system for the Graphic Powers team to manage customers, licenses, sales, support cases, and business data. Gives the team full oversight and control over the entire customer lifecycle and licensing flow.",[1386,1401,1403],{"id":1402},"licensing-system","Licensing system",[16,1405,1406],{},"Complete license management for Graphic Tracer — from trial periods and monthly subscriptions to lifetime licenses. Handles activation, validation, and upgrades for customers globally.",[11,1408,144],{"id":143},[27,1410,1411,1413,1416,1418],{},[30,1412,572],{},[30,1414,1415],{},"Vue.js \u002F TypeScript",[30,1417,581],{},[30,1419,1420],{},"SQL Server",{"title":158,"searchDepth":159,"depth":159,"links":1422},[1423,1424,1429],{"id":13,"depth":159,"text":14},{"id":538,"depth":159,"text":539,"children":1425},[1426,1427,1428],{"id":1388,"depth":518,"text":1389},{"id":1395,"depth":518,"text":1396},{"id":1402,"depth":518,"text":1403},{"id":143,"depth":159,"text":144},"Graphic Powers AB","2018-06-01","Website with Stripe-integrated store, web-based administration system, and licensing system for a Swedish software company with global customers.",{},11,"\u002Fportfolio\u002Fen\u002Fgraphic-powers",{"title":1372,"description":1432},"portfolio\u002Fen\u002Fgraphic-powers",[177,178,179,1367,1439,1440],"stripe","licensing","\u002Fimages\u002Fportfolio\u002Fgraphic-powers-website.png","EATjWD-94E_P42iwYcAXUtyOqh481hnDzXlJuqLrKBg",{"id":1444,"title":1445,"body":1446,"client":1581,"date":1359,"description":1582,"extension":169,"featured":170,"meta":1583,"navigation":170,"order":1584,"path":1585,"seo":1586,"stem":1587,"tags":1588,"thumbnail":1589,"__hash__":1590},"portfolio_en\u002Fportfolio\u002Fen\u002Fwebsec-assistant.md","WebSec Assistant — Security-awareness browser extension",{"type":8,"value":1447,"toc":1576},[1448,1450,1461,1464,1467,1469,1533,1535],[11,1449,14],{"id":13},[16,1451,1452,1453,1456,1457,1460],{},"WebSec Assistant is a Firefox extension built to raise everyday security awareness inside an organisation. Rather than training users once a year and hoping it sticks, the extension rides along with their browsing and does two things at once: it ",[33,1454,1455],{},"protects"," them in the moment — blocking known-bad domains, flagging weak passwords, warning on phishing-prone sites — and ",[33,1458,1459],{},"teaches"," them in small, context-aware doses, opening topic-specific guides with quizzes and optional audio narration exactly when a risky situation comes up, so the explanation lands while the context is still fresh.",[16,1462,1463],{},"Each organisation gets its own allow\u002Fdeny rules against a company-scoped backend, so the same extension can be rolled out across different tenants without rebuilding anything.",[16,1465,1466],{},"The project was featured by IVA (Kungl. Ingenjörsvetenskapsakademien) as a research initiative with commercial and societal potential.",[11,1468,25],{"id":24},[27,1470,1471,1481,1487,1497,1503,1509,1515,1521,1527],{},[30,1472,1473,1476,1477,1480],{},[33,1474,1475],{},"Domain blocking"," — Known-bad URLs are intercepted via the WebExtension ",[310,1478,1479],{},"webRequest"," API and redirected to a categorised warning page (malware, phishing, spam, or fake news). Dangerous categories require an explicit action to continue",[30,1482,1483,1486],{},[33,1484,1485],{},"Per-session bypass"," — Users can whitelist a domain for the current tab only, or permanently, straight from the warning page — or jump directly into the matching learning guide",[30,1488,1489,1492,1493,1496],{},[33,1490,1491],{},"Password strength tooltip"," — When a password field gets focus, an in-page tooltip powered by ",[310,1494,1495],{},"zxcvbn"," rates the password on a five-level scale with a colour-coded bar, and can inject the tested value back into the form",[30,1498,1499,1502],{},[33,1500,1501],{},"Phishing popup on webmail"," — On common webmail domains, a reminder of phishing red flags appears when users are most likely to need it",[30,1504,1505,1508],{},[33,1506,1507],{},"External-link warning"," — New-tab navigations to external destinations can be flagged so users aren't silently redirected somewhere unexpected",[30,1510,1511,1514],{},[33,1512,1513],{},"Interactive topic guides"," — Password, phishing, scamming and fake-news guides are delivered as short slide decks with multi-choice quizzes, live visual feedback, Howler-based audio narration and a completion screen",[30,1516,1517,1520],{},[33,1518,1519],{},"Manual blocklist refresh"," — One-click sync with the organisation's backend, plus a visible timestamp of the last successful update",[30,1522,1523,1526],{},[33,1524,1525],{},"Bilingual UI"," — Full English and Swedish translations, including extension-store metadata",[30,1528,1529,1532],{},[33,1530,1531],{},"Configurable"," — Each protection feature (password tooltip, domain blocking, external-link warning, phishing popup) toggles independently",[11,1534,144],{"id":143},[27,1536,1537,1552,1558,1567],{},[30,1538,1539,1542,1543,788,1545,788,1548,1551],{},[33,1540,1541],{},"Extension:"," Vue, WebExtension APIs (",[310,1544,1479],{},[310,1546,1547],{},"storage",[310,1549,1550],{},"tabs","), Shadow DOM styling (host-page CSS can't leak in), zxcvbn (password scoring), Howler (per-slide audio)",[30,1553,1554,1557],{},[33,1555,1556],{},"Architecture:"," Long-running background script owns blocklist + whitelist state and talks to the backend; content script renders UI inside Shadow DOM; popup, guide and warning are three separate Vue entry points",[30,1559,1560,1562,1563,1566],{},[33,1561,155],{}," Company-scoped REST API at ",[310,1564,1565],{},"ubarso.xenolith.se"," for per-tenant blocklist configuration",[30,1568,1569,1572,1573,495],{},[33,1570,1571],{},"Manifest V2",", Firefox-first (Gecko add-on id ",[310,1574,1575],{},"websecassistant@xenolith.se",{"title":158,"searchDepth":159,"depth":159,"links":1577},[1578,1579,1580],{"id":13,"depth":159,"text":14},{"id":24,"depth":159,"text":25},{"id":143,"depth":159,"text":144},"Xenolith AB (research project)","Firefox extension that protects users from phishing, weak passwords, and scams — and teaches them why, with interactive topic guides and quizzes.",{},12,"\u002Fportfolio\u002Fen\u002Fwebsec-assistant",{"title":1445,"description":1582},"portfolio\u002Fen\u002Fwebsec-assistant",[1231,178,1232],"\u002Fimages\u002Fportfolio\u002Fwebsec-assistant-hero.jpg","hNz6_tDIprZcmiDw35tuCcBzZoI8nLv02cn0wydzvRg",1776248144558]