work, experience and skills
This portfolio strives to comprehensively present my personality and work, but primarily focuses on professional activities in the field of software engineering and information technology.
The need for creation, curiosity, the need to understand the world around me, and a thirst for new knowledge—which from the earliest years found their most fertile ground in software, and informatics and computing in general.
At twelve years old began my daily journey through code and computer systems—from microprocessor architecture to the sophisticated levels of abstraction that characterize application software today.
After more than a decade of practical engagement with computers, and almost a decade of writing software, today I can present my technical knowledge as the result of years of consistent dedication to every aspect of software development—from basic logic and understanding hardware limitations to complex architectures of distributed systems.
What emerges is less a collection of skills than a way of working. The same attention that goes into debugging a production incident goes into shaping a reusable abstraction, or refactoring an old module to match a cleaner mental model. The job is never merely to ship—it is to leave behind code that the next engineer will want to read, and systems that continue to explain themselves long after the original author has moved on.
"I see myself as homo poeticus who seeks creative synthesis through all aspects of work.
All of this converges, or rather: all of this is the convergence. The code I write carries the same aesthetic demand as the sentence I construct. The architecture of a distributed system mirrors the architecture of an argument. There is no separation between technical and humanistic—that distinction belongs to an era of specialization I refuse to inherit.
The literary tradition that shaped my thinking runs through the French moralists and Russian maximalists in equal measure—André Gide's acte gratuit and the liberation of authentic action, Proust's obsessive archaeology of memory and time, Dostoevsky's unflinching descent into the cellars of human psychology where logic dissolves into paradox.
Philosophy functions here not as academic credential but as operational framework. Kierkegaard's leap remains the founding gesture—the recognition that at some point analysis must yield to commitment, that infinite reflection is paralysis dressed in sophistication.
Philosophy gives you the questions. Engineering demands the answers. Between the thinking and the building lives the work that matters — late nights, broken deploys, elegant solutions, and the slow accumulation of craft.
Seven roles, two acts — engineering, and the craft around it.
Logic, structure,
the long refinement.
After more than a decade of practical engagement with computers, and almost a decade of writing software, I can present my technical knowledge as the result of years of consistent dedication to every aspect of software development — from basic logic and hardware limitations to the complex architecture of distributed systems.
My starting point was a simple fascination with creating something from nothing using code; over time it became a professional orientation in which I mastered almost every segment of modern software development.
Already at twelve I built my first static web pages — a field of experimentation, but also an introduction to systematic, structured thinking. As my interest grew, focus shifted to dynamic systems, where I began developing my own frontend applications, paying special attention to interface, experience and accessibility.
Soon after, backend logic became the natural next step: building APIs, implementing business logic, and solving the problems that appear when applications must talk to databases, manage users, respect security and scale. What shaped me most was going through every phase independently — idea, design, implementation, testing, deployment, optimization — which forced me to understand how each layer works and how they coexist.
Over time I built solutions that resist simple patterns — web portals for news agencies, e-commerce with complex inventory and payment logic, internal analytics tools, and services drawing on many APIs: financial, crypto markets, health standards. Connecting that many sources and interfaces meant constantly minding performance, security and scalability.
In recent years I have focused intensively on mobile, with Expo and React Native at the core — not extended web interfaces but independent products using geolocation, offline capability, authentication, push notifications and the camera, with a deep grasp of the whole ecosystem, from state and local databases to UI performance and store distribution.
Authentication and security hold a special place: I have always built my own login systems rather than settle for ready-made libraries, designing flows for every scenario — multiple devices, automatic token renewal, abuse protection, identity verification — tested on real users in production.
My deepest competency is broader architecture — systems that grow and live for years without falling when users multiply tenfold. One result I am proud of: verifying authentic physical locations without the Google Places API (now largely withdrawn from open use), by combining web scraping, AI analysis, local heuristics and many public and closed sources.
A special focus is the practical application of AI. Within my startup I built an AI assistant that personalizes the experience through contextual content — connecting people with events, places and points of interest by behavior, location and interest — combining data analysis, semantic processing, geolocation and vector search. The work spans LLM integration through APIs and retrieval-augmented generation: embedding models, vector databases and proprietary filtering to search by meaning, not form.
I am comfortable building the interface logic that talks to LLMs — conversational flows, fallback mechanisms, relevance evaluation — for real control over AI behavior. And beyond practice: during my software-engineering studies I chose electives in machine learning, statistical modeling and AI for a deeper mathematical foundation.
Whatever the web needs — built on Next.js and Nuxt over Strapi and Drizzle, one typed codebase from database to DOM.
One React Native codebase on Expo, shipped to both stores — typed, with live data and encrypted messaging.
Typed Node services over Postgres — REST and WebSocket, encryption, and the schemas everything else is built on.
Turborepo monorepos through Docker and CI to AWS, GCP and Cloudflare — typed configs, deploys gated on lint, types and tests.
Project manager, designer, art director.
Roadmaps, scope and milestones across five products — one person holding the plan from first ticket to release.
Editorial type, motion and interface systems in Figma — then built in code, not handed off.
One visual language across the whole product — type, colour, rhythm, restraint — set once and held on every screen.
Make a thing. Then make it again, better.
I started BLink with Petar Kremenović because the city we live in still needed building — a digitized public-transit system, a civic platform that closes the loop, ride-hailing tuned to a local market. A smart-city stack, plus founder tools nobody else was building. So we started a startup.
06 — startup
Petar Kremenović and I founded blink in Banja Luka in 2024 — one startup building five products, each already live with its own users, all shipped by the same small team.
banja luka · since 2024

clinic operating system · live · 2025
A practice runs on four tools that never talk: paper schedules, an Excel of invoices, scattered email threads, no record a patient can see. Sinapsa folds the whole patient lifecycle into one codebase — a marketing site that books, an admin console for the clinic, and a private portal for each patient.
Next.js 16PrismaStripe
Beyond booking
Three independent interfaces mounted from a single Next.js App Router build — each with its own authentication and strictly separated data boundaries. If one gate falls, the next layer still refuses.
The clinic's central workspace — sections across scheduling, records, billing and settings, each gated by RBAC.
A private, branded space for each patient. Every query is scoped to that user's clientId.
The public site with built-in booking and lead capture. Renders from a CMS, with a JSON fallback when the CMS is offline.
The functional range a generic booking tool never reaches — from patient acquisition through clinical records to finance.
Full appointment lifecycle: session types, statuses, weekly availability grid, blocked time, recurring and group sessions. Server-side conflict detection prevents double-booking.
Two structured note formats — SOAP and DAP — with a Draft → Finalized lifecycle. Treatment plans track progress per goal. Standardized assessments: PHQ-9, GAD-7, DASS-21 with severity and trend.
Auto-numbered invoices with PDF generation and statuses. Revenue tracking, expenses by category, session packages. All money is held as Decimal(10,2).
Five built-in workflows — reminder, follow-up, no-show, payment, welcome — over email and SMS, with configurable triggers and a log of every message sent.
Revenue, attendance rate, session-type mix, new vs returning patients. Time ranges, donut and stacked charts, drill-down and PDF export. Chart labels reach screen readers.
Five admin roles plus a portal role, 27 named permissions. Every create, edit, delete, login and export is logged with user, time and affected record. 2FA and active-session control.
The platform handles protected health information. Every state-changing request runs a chain of checks before it touches the database — the boundary never rests on a single layer.
clinical:write?A walk through the admin console, the marketing site and the patient portal — captured from the running application.








Development ran as end-to-end campaigns, not a feature pile — each round closed findings across many subsystems before the next began. Every round had an audit, then a fix bundle, then a merge through review.
Move to Next.js 16 + Prisma + NextAuth. Marketing CMS with JSON fallback, portal redesign, booking flow with OTP and Turnstile, Telegram AI bot.
Spam-score engine with 10 signals, honeypot, sliding-window rate limiter, double-booking prevention, crypto.randomUUID meeting links, audit on all booking ops.
Upstash rate limiting, SMS OTP, Sentry, password reset, security headers, database indexes, CI/CD pipeline, a complete .env.example.
Happy-path through a performance suite, visual consistency, portal and admin lifecycle tests, API auth-boundary tests, cross-system workflow e2e.
Critical / high security fixes, e2e CSRF coverage of every mutating admin route, two passes of jsx-a11y and hooks lint cleanup (120+ warnings).
Motion presets, layoutId active indicator with spring physics, bento dashboard, 2FA rate limit + audit + origin check, password reset invalidates all sessions, sanitized every dangerouslySetInnerHTML input.
Moved payments / packages / expenses onto money.ts, Stripe rounding-drift fix, GDPR coach scope on export, audit-row preservation under GDPR Art. 5(2), coach-timezone date math for blocked time.
Closed IDOR holes on notes, assessments, plans, medications and risk assessments. Real Stripe refund calls, handling of refund / dispute / failed webhook events, password floor raised to 12 characters.
Added clinical:read/write/delete permissions, READ_ONLY blocked from PHI mutations. CSP frame-ancestors, Sentry header redaction, native confirm() replaced with Radix dialogs, 44×44 touch targets.
Server-shell rendering, react-query tuning, N+1 fixes. Cron jobs write one audit row per run, alert on failure, idempotent reminders. Marketing SEO and structured data.
Empty / loading / error states, mobile cards, live template preview, DSR timeline with SLA timer and export receipts, drill-down analytics, invite flow with role badges — 20+ admin sections combed through.
README, CONTRIBUTING, runbooks (incident response, cron, auth recovery, backup / restore), compound DB indexes, an a11y / i18n pass, a DEMO_MODE that neutralizes destructive operations, generalization into a clinic SaaS.
Modern, typed, serverless-first. No secrets in code — everything through environment variables.
PHI and GDPR are not an afterthought — they are wired into every route, transaction and cron job.
Five admin roles plus a portal role, 27 named permissions. Each API endpoint checks the caller's role before returning data.
Every create, edit, delete, login and export — with user, time, record and severity (Info / Warning / Critical). Filterable and exportable.
Export (a JSON bundle of every row tied to a client) and erasure (cascade delete + tombstone audit). Per-DSR SLA timers, bulk consent, export receipts.
Optional TOTP 2FA with hashed backup codes and trusted devices. Review and kill active sessions per device. Passwords 12+ characters.
Origin check on all state-changing routes (App Router ships no CSRF tokens by default). Strict CSP with frame-ancestors 'none' and a tight default-src 'self'.
An ML-based spam score (behaviour, timing, content) + IP rate limit + Cloudflare Turnstile on every public form. Admin review queue and blocklist.
A production platform, not a demo — the whole patient lifecycle in one codebase, hardened across eleven rounds.
a civic operating system · live · Banja Luka · 2026
Local government here is paper-first and fragmented: to report a broken streetlight, find the right office, or understand a permit, a citizen calls, queues, and digs through scanned PDFs in the official gazette. Urbano is the single digital front door — one account and one brand across a citizen app, an admin console, a public API, native mobile, and a RAG assistant that actually answers questions about how the city works.
TypeScriptReact + Vitepgvector RAG
From paper queue to one account
Urbano is split across subdomains on purpose — each a distinct product with a distinct job, but sharing one design system, one account (SSO) and one backend. Front-ends are dumb static bundles on Vercel; all logic lives in two Express APIs on Railway, both talking to Neon Postgres.
The heart of the platform — a rich SPA where residents live with the city day to day.
The flagship differentiator — a RAG assistant that demystifies city bureaucracy, grounded in real documents.
The back office and the single Express API powering web, mobile and admin alike.
The part I am proudest of, because getting it trustworthy — not just plausible — for a government context took real engineering. A confidently wrong answer about a legal procedure is worse than no answer.
The top matches become grounded context for gpt-4o-mini, which streams the answer over SSE. The model emits structured blocks the front-end renders as rich UI — procedure card, documents checklist, embedded map, hours table.
Asked to register a d.o.o. (a court matter, not a city one), it declines plainly and points to the right institution instead of inventing a fake city procedure. Competence boundaries in the system prompt stop it conflating look-alike concepts (sole proprietor ≠ limited company).
Every answer carries its sources; clicking one opens the official document and auto-highlights the passage — #search= for PDFs, #:~:text= for HTML — with no object storage stood up.
When a topic is out of scope, the assistant shows a card inviting a vote (and optional email) to have it added. Votes land in a scope_interest table — honesty turned into a demand-driven backlog.
A single query runs a guarded retrieval-and-generation pipeline — ~22,315 chunks of often-Cyrillic, often-scanned city documents behind a pgvector HNSW index, with guards at each step so the assistant stays grounded.
text-embedding-3-large → 1536-dim:::procedure / :::documents blocks over SSEA walk through the citizen app, the assistant and the city console — every shot taken from the running production sites on *.ekomunalac.com.








The stories that don't fit in a one-line bullet — the ones that show the actual engineering. Each is written up in full in the project's deep-dives.
The city's WordPress base64-encodes its PDF URLs into ###УРЛ_<base64>### placeholders unless you send Cookie: rstr_script=lat — the query param does not work. Without that single header the documents are literally un-downloadable.
An LLC question retrieved sole-proprietor docs scoring 0.55–0.63 — above any floor — and produced a confident, wrong procedure. A threshold can't catch it: the wrong docs are relevant by cosine. Fixed with competence boundaries in the prompt and citation suppression on out-of-scope answers.
~690 chunks were gibberish from scanned map sheets. The obvious "delete low word-ratio chunks" heuristic was measured and rejected — it flagged 961 chunks, catching legitimate numeric tables (timetables, budgets). Solved at the retrieval/UX layer, not by destroying production data.
Marketing and the app are the same Vite deployment, switched by hostname: web./app. boot the product, the root domain boots marketing, and a ?view= override simulates both in local dev. One build, no duplication.
The Komunalac API is the identity provider (Google One-Tap → HS256 JWT); the Asistent holds the same secret and verifies the token as a relying party. A single identityKey() resolves to user:<id> or falls back to device:<id> for anonymous users.
Shipping one nested app from a big pnpm monorepo to Railway with no dashboard — a custom Dockerfile + RAILWAY_DOCKERFILE_PATH and a filtered pnpm install --filter "@urbano/api...". The 502 that wasn't a crash: a domain pinned to the wrong target port, fixed via Railway's GraphQL API.
The Trezor stores national IDs, tax IDs and addresses to auto-fill forms. Payloads are encrypted with AES-256-GCM in a { v, iv, tag, ct } envelope; the key lives only in the server environment, so the data is opaque at the database layer.
TypeScript everywhere, strict, with Zod validating every external input. Seven deployable apps in one pnpm + Turborepo monorepo — no secrets in code.
For a civic product, being trustworthy is the feature. The hard work is the non-obvious kind — refusing the confident wrong answer, and refusing the destructive shortcut.
The citizen vault is AES-256-GCM encrypted in a versioned { v, iv, tag, ct } envelope; the key never leaves the server environment, so the database only ever holds ciphertext.
A single identityKey() keys the vault and the daily quota off user:<id> when logged in and device:<id> otherwise — so anonymous data can later migrate to an account.
An explicit competence map points every out-of-scope topic to the correct external institution, and contradictory citations are dropped before they reach the user.
The OCR-garbage cleanup refused a destructive batch op because a heuristic "looked right" — it sampled the false positives first, then chose the non-destructive retrieval-layer fix.
Redis, MongoDB and Kafka are optional; if they're down the core product still works — cache, rate-limit and logging degrade gracefully rather than taking the city offline.
Every external input — env, request body, params, query — is validated by Zod, with shared types and schemas living in @urbano/shared rather than duplicated client and server.
A production platform across five subdomains, not a demo — deployed pre-launch with the full RAG pipeline serving real city documents. Usage metrics are intentionally omitted; the achievements here are architectural and engineering ones.
real-time transit · in development · Banja Luka · 2024
Static schedules were wrong the day they were printed. BLBus streams verified vehicle positions off a live GTFS-realtime feed — the next arrival ticks down, then flips to LIVE.
React NativeGTFS-RTWebSocket
From guess to live
ride-hailing · in development · Banja Luka · 2024
Global ride apps assume card-only cities ten times our size. Djir runs cash and card through one booking flow, with fares you read before you book and a commission low enough that driving pays.
React NativeExpoNestJS
Tuned to the ground
operational cli · in development · 2025
Running a company alone means being the deploy engineer, the PM, and the person who writes the Friday update. Jared takes the recurring work — ships deploys, drafts status from your commits, runs the weekly review.
NodeClaude APICobra
The recurring work, automated
A contribution graph is just colored squares — until you read it as a calendar. Each square is a day something got built, fixed, or broken and rebuilt. The interesting part is not the streaks but the gaps — the weeks spent reading, rethinking, or simply living. Consistency is not about never stopping. It is about always returning.
Years of commits, experiments and shipped systems compressed into one field of work.
Before the first function, there was a sentence. Dostoevsky taught that reason has limits. Kierkegaard, that the leap is the only honest move. Proust, that attention is the rarest form of generosity. Every book left a residue — not knowledge, but posture. The way you hold a problem. The patience before the elegant solution. Code is written in languages, but thinking is shaped by literature.
The eye learns before the hand. Every interface begins as a gaze — a fraction of a second where the visitor decides: stay or leave. Beauty is not ornament. It is the shortest path to trust.
Off the clock — the screen after midnight, golden hour on film, and the quiet hours in between.
Quiet correspondence preferred. For anything urgent — a voice call cuts through faster than a thread.
Thereisacrackineverything
That’showthelightgetsin
Thank you
for sticking to the end.
scroll on — return to I, opening frame follows