Projects
A selection of technical work, ideas, and ongoing experiments. Some entries are mature, others are still evolving.

We have a vacation home in the mountains of Bosnia where my dad was raised. The location of the home is quite remote and deep in the mountains, at an altitude of roughly 700 m. Home networks in those places with cable connections are a rarity. Simply because there are virtually no cables running below the gravel roads through the mountains. Therefore, cable internet was never an option. But even mobile network coverage there is very low. The occassional phone calls work just fine. Getting a mobile internet signal, however, is a different story. I remember having to stand in very specific places, such as on the balcony, to get even one signal bar for stable internet calls.

There are several reasons for the lacking mobile network coverage in remote places in Bosnia. For one, the network infrastructure is not nearly as mature as in other countries. The next cell tower could be several kilometres away. Additionally, being in mountainous regions can exacerbate the problem when hills cut the line of sight to these cell towers. At our remote vacation home, we are facing both of these problems. Therefore we have been searching for solutions to the lack of connectivity since a couple of years.

Since mobile internet signals reach only certain spots of our home, we went straight to a satellite internet solution. For this, we looked for viable contracts from Germany to our place in Bosnia and found the provider Filiago. Their service was good and even though we paid a hefty sum of 50 € for 10 GB of data per month, we finally had a stable internet connection for simple home use.

Illustration A: View from our balcony with the satellite antenna installed.

The satellite modem was a Viasat Surfbeam 2 and it worked out of the box after installing the antenna, positioning it to Eutelsat 9° East, and connecting it. The latency of roughly 700 ms was expected but didn't bother us too much, as we have never had the requirement of real-time usage. After two years, though, we faced a couple of issues. First, shortly after the Ukraine-Russia war started, we lost internet connection abruptly. The provider contacted us and said that this is likely due to a Russian hacking incident. Interestingly enough, the whole modem was fried. It didn't turn on anymore, which, at that time, was quite concerning. I was wondering how you can break modems remotely with, what I can only assume, remote infiltration and placing of malicious payloads(?) to the modem. In any case, the provider sent us hardware replacements free of charge and everything worked fine after reinstalling the modem. However, after a couple of months the prices at Filiago increased by another 20 or 30 € per month for the same data package and we decided to end the contract.

We were then looking for other solutions and the network class I had taken a couple of months earlier during my stay abroad at Tallinn University of Technology gave me an idea. In the class, we had worked with both directional and omnidirectional antennas for signal enhancements of Bluetooth, RFID, and other signals. Since network signals at our remote place are coming from single, distant directions, I was immediately thinking of using a directional antenna to amplify the signals that do come through to certain spots in our home. This, in combination with a simple 4G router would give us a simple and much cheaper solution.

So I started my search for a simple directional antenna and the first thing that came to mind was a Yagi antenna. Ah yes, the good old Yagi antenna. High directional gain, simple construction, and it's dirt cheap. It seemed though that Yagi antennas specifically for 4G/LTE signals are quite nieche. At least I couldn't find many reliable results on the usual shopping sites. I tried my luck and bought following Yagi antenna with almost no reviews: Yagi antenna.

Illustration B: The Yagi antenna in the hands of my dad during setup.

In this context, I also did some research on the frequency bands for common mobile signal frequencies:

Illustration C: Frequency bands for common mobile network technologies.

I learned that technically, 4G and LTE use the exact same frequency spectrum. LTE (Long Term Evolution) is simply the technological standard that makes 4G possible. 4G was originally a strict speed standard defined by the ITU (International Telecommunication Union). LTE was developed as the technology path to eventually reach the 4G standard. Early LTE also fell short, but LTE-Advanced finally hit the true 4G mark. Today, the terms are used interchangeably.
I also figured that using lower frequency bands would make more sense in our scenario, as the network signal is generally low. As 5G is not really established in many parts of Bosnia yet, we didn't have to worry about any of those high frequency bands above 3 GHz. Ideally, we wanted to hit some bands below 1 GHz, as those signals travel much farther and penetrate obstacles, like trees and hills, better than higher frequencies. We settled for a TP-Link Archer MR200 as our 4G router. Setting the right frequency bands in the tp-link web interface was straightforward. I then bought an RG174 coaxial cable and some adapters for good measure to make sure that the cable going from the Yagi antenna to the router fits. Remember, driving one way from our place in Germany to our vacation home is roughly 1000 km. I wanted to avoid the search for adapters and cables locally in Bosnia at all costs, as it is generally very hard to find such specific hardware there. The sim card we bought from a local network provider for the 4G router was surprisingly cheap, with a couple dozen GB of data per month for roughly 10 €. What an improvement already to the satellite solution! But the important question was: Would it all work properly?

We then set up the router with the sim card and replaced one of the standard antennas with the cable going to the Yagi antenna on the balcony:

Illustration D: Home router with one standard antenna and the Yagi antenna.

I was contemplating for a short time using the satellite dish that was still installed from the previous satellite internet setup to craft a parabolic directional antenna. A directional antenna, much like a flashlight compared to a light bulb, concentrates the power supplied by the transmitter into a narrower space. With this, it increases the signal strength in a specific direction. This focus is what is meant by antenna gain or amplification:

Illustration E: Functionality of a directional antenna for signal gain.

In theory, using the Yagi antenna in front of the parabolic satellite dish should yield a better signal coverage under certain circumstances:

Illustration F: Functionality of a directional antenna in combination with a parabolic antenna.

Standard parabolic dishes are designed for C-band frequencies, which sit just above the S and L bands used by terrestrial LTE. For higher LTE bands (1800 MHz and up), the dish acts as a massive signal concentrator, but its effectiveness drops at lower frequencies where wavelengths are too large for the dish's physical diameter to reflect accurately. To make a Yagi work in this setup, it must be a compact, high-frequency model specifically positioned so its active element sits at the dish's exact focal point. This essentially turns the Yagi into a super-feeder. Under some circumstances, this setup also requires additional hardware, such as a diplexer. However, while a diplexer could theoretically combine this dish-boosted signal with a secondary antenna's input, more problems like phase alignment arise. Related: RE-PURPOSE SATELLITE DISH TO CUSTOM DIRECTIONAL ANTENNA. In the end, using a MIMO antenna to repurpose a satellite dish would be less of a hassle though and most likely more efficient as well.

While I would have loved to repurpose the satellite dish previously used for satellite internet, I didn't want to and didn't have to take such drastic measures. Especially since we were operating in low frequency bands and the Yagi antenna should, with its highly directional properties, be enough to amplify the weak signal that we do receive. And indeed, with some fiddling, we achieved some good signal strength with the standalone Yagi setup! Tweaking some additional settings for the router, positioning the router itself properly, and fixing the Yagi antenna in place on the balcony gave us a stable enough connection to do our daily business without hassle.




This is a project for all you static website enjoyers out there! The idea for this project was born from the need to add dynamic functionality to a static website without the overhead, cost, or security risks of maintaining a dedicated backend server and a traditional database (like SQL or MongoDB).

The solution leverages edge computing. I designed a system where a private GitHub repository acts as a flat-file database (storing JSON). A Cloudflare Worker, a serverless function running on Cloudflare's global network, acts as the safe middleman, handling authentication and processing data between the client's browser and the GitHub API.

The Data Flow Architecture

The primary challenge was security: how can a client website write to a private GitHub repo without exposing a Personal Access Token (PAT) that has write permissions? The answer is never allowing the client to see the token.

Illustration A: System Architecture (Logging Data)
+-------------------+       Encrypted POST      +-------------------+
| Client Browser    |-------------------------->| Cloudflare access |
| (StatiCrypt Page) |    (JSON Session Data)    | (Worker Trigger)  |
+-------------------+                           +-------------------+
                                                        |
                    [Safe middleman handles auth]       |
                                                        V
+-------------------+     Authenticated PUT     +-------------------+
| GitHub Private    |<--------------------------| Cloudflare        |
| Repo Datastore    |   (Includes Hidden PAT)   | Worker Function   |
| (sessions.json)   |                           | [process & auth]  |
+-------------------+                           +-------------------+
                                    

As shown in Illustration A, when a user logs a session:

  1. The user authenticates via the StatiCrypt protected page. This ensures only authorized users access the form.
  2. The browser sends the data via HTTP POST to a unique Cloudflare Worker endpoint.
  3. The Worker function wakes up. It retrieves my PAT, which is securely stored within Cloudflare as an encrypted Environment Variable.
  4. The Worker performs necessary data validation or formatting.
  5. The Worker uses the Fetch API to communicate with the GitHub API, using the hidden PAT for authentication, to update the JSON file in the private repository.
Illustration B: System Architecture (Fetching History)
+-------------------+         HTTP GET          +-------------------+
| Client Browser    |-------------------------->| Cloudflare access |
| (Portfolio Site)  |    (Request History)      | (Worker Trigger)  |
+-------------------+                           +-------------------+
                                                        |
                                                        |
                                                        V
+-------------------+     Authenticated GET     +-------------------+
| GitHub Private    |<--------------------------| Cloudflare        |
| Repo datastore    |   (Includes Hidden PAT)   | Worker Function   |
| (sessions.json)   |                           | [fetch & serve]   |
+-------------------+                           +-------------------+
                                    

Illustration B shows the flow for displaying information. The portfolio site requests the practice history through the Worker. The Worker fetches the private JSON file from GitHub using the hidden token, performs any required sorting, and serves it back to the portfolio site as a clean JSON response.

Key Security Components

This architecture solves several critical security hurdles inherent in static site development:

  • GitHub Token Protection: By using Cloudflare Workers as a mediator, the PAT required to write to GitHub is never exposed to the client browser. It remains securely within the Cloudflare environment.
  • StatiCrypt Protection: The submission form itself is encrypted using StatiCrypt. This adds a layer of authentication, ensuring that only users with the password can even see the form or trigger the Worker to add new data.
  • Flat-File Database: Using JSON in a private repository is a high-availability, zero-cost, flat-file database solution perfectly suited for low-frequency, structured data logging.

This approach demonstrates how edge computing can provide robust backend functionality to static sites, prioritizing security and cost-efficiency. If you are curious, I implemented this functionality for our Jazz band that I perform with regularly: The Elevators.
For obvious reasons, the demonstrator is only accessible via login, but feel free to explore the rest of our website ;-).




At work, I am always looking for opportunities to collaborate with industry partners. Since my research is generally theoretical, such collaborations provide the opportunity to apply technologies to real life use cases and systems. This is why I held a webinar together with MathWorks and SYSGO on the topic Software Development and Integration in Safety-Critical Aerospace Systems. The webinar focuses on development and integration challenges in modern aerospace software systems, with particular attention to model-based approaches and the role of tooling in safety-critical contexts.

The work presented in the webinar is based on a previously published collaborative effort between the German Aerospace Center (DLR), MathWorks, and SYSGO. The publication discusses practical questions around structured software development, system integration, and validation in avionics environments. In that sense, the webinar served both as a technical presentation and as a way of communicating the broader ideas behind the underlying research to a wider engineering audience.

The related paper is available here: Systematic Approach to Model-Driven Development of Reconfigurable Avionics Systems.
The webinar recording is provided below:




I like to use scalable images whenever possible (ignore the images used in this entry below!!). Taking screenshots of MATLAB GUIs has been a little frustrating in this regard: how do you capture application windows as scalable images rather than simple raster screenshots? In many cases, the real goal is not just to "take a screenshot," but to export the visible GUI state in a format that remains sharp when zooming or printing. PDF export is particularly useful here because it preserves quality much better than a standard bitmap capture.

What makes this topic interesting is that MATLAB currently spans two different GUI worlds. For a long time, many MATLAB windows were handled as UI figures, that is, objects of type matlab.ui.Figure. More recently, MathWorks has been moving parts of its interface stack toward web-based windows built on top of HTML content served locally and rendered through the Chromium Embedded Framework (CEF). These windows are exposed internally through objects such as matlab.internal.webwindow.

From a user perspective, both may appear as ordinary MATLAB application windows. From a technical perspective, however, exporting them is fundamentally different. That difference is exactly what makes this problem slightly obscure: the correct export method depends on the kind of window you are dealing with.

A useful background reference on this broader transition is the Undocumented MATLAB article on customizing UI figures: Customizing uifigures, part 1 .

For classic UI figures, the main challenge is often simply obtaining the correct figure handle, especially if the application was not developed from scratch and the relevant figure handle was never stored explicitly during creation. In such cases, one practical approach is to search for the window by name:

fig = findall(0, 'Name', 'MyApp'); exportapp(fig(1), 'MyApp.pdf')

The first line searches for figures whose displayed window title matches the requested name. The second line exports the selected figure directly to PDF using exportapp. In practice, the handle search may return multiple figures, which is why selecting a specific entry such as fig(1) is often necessary. It is therefore worth checking the size and contents of the returned variable before exporting.

This workflow is relatively straightforward once the handle has been identified. For UI figures, PDF export is well-behaved and can serve as a simple way to capture the current state of an app window as a scalable artifact.

Chromium-based web windows are more complicated. These are internally managed through MATLAB's web window infrastructure and are less prominently documented, which makes this a somewhat niche topic. In that case, the relevant approach is based on the internal web window manager:

webWindows = matlab.internal.webwindowmanager.instance.findAllWebwindows(); webWindow = webWindows(1); webWindow.printToPDF('MyApp.pdf')

Here, all currently active web windows in the MATLAB session are retrieved first. Then, as with the UI figure case, the relevant window has to be selected manually from the returned list. Once the desired object is identified, printToPDF can be used to export the Chromium-rendered content directly to a PDF file.

One practical complication is that the list may contain several unrelated internal windows, depending on what else is open in the MATLAB session. That means the selection step is important, and in real workflows it is often helpful to inspect the returned objects and identify the correct candidate before calling the export method.

An interesting side note is that MATLAB also exposes Chromium developer functionality for these web windows. For instance, the DevTools for a given window can be opened programmatically:

webWindow.openDevTools
Illustration A: Screenshot of the developer tools for web windows.

This is surprisingly useful when trying to understand how a particular application window is rendered internally. It also confirms quite directly that parts of the MATLAB GUI stack are effectively running as locally served web applications inside embedded Chromium windows.

In the same spirit, the web window manager can also expose the local session URL associated with a given window. These URLs typically point to a localhost or loopback address, for example:

https://127.0.0.1:31516/toolbox/systemcomposer/repository/project_app/web/index.html
Illustration B: Web session of a selected web window.

This is a nice reminder of what is actually happening under the hood: the interface is not just a traditional desktop widget hierarchy, but an HTML-based application served locally and rendered via CEF.

Overall, the main lesson from this topic is that exporting MATLAB windows as scalable graphics is not a single universal operation anymore. It depends on whether the window is a classic UI figure or a Chromium-backed web window. In any case, the resulting scalable screenshots are much better suited for publications or archived design artifacts.




This project started from a fairly simple observation: when visiting a new city, it is often difficult to find places that match a specific taste or atmosphere. Standard search tools usually surface the bigger and more obvious venues first, while smaller or more specialized places are much harder to discover.

The original idea was to build a mobile application that helps users discover bars, clubs, restaurants, and other venues in a more targeted way. In particular, I was interested in the idea of finding places with a specific character or theme that are often known mainly through local word of mouth.

I already explored the concept technically and created a project in Android Studio. The longer-term goal is to build a first working version that combines a map-based interface with a structured list of venues and their most relevant information.

At the moment, this entry serves as a placeholder for a future write-up. More details will be added once the concept and implementation mature further.




This project emerged from a practical networking problem. Standard consumer WiFi extenders work well in many home environments, but they are often not suitable for networks that use WPA2-Enterprise / 802.1x authentication, such as those commonly found at universities or in public institutions.

The idea here is to explore whether a Raspberry Pi can be used as a more flexible intermediate system: authenticating properly against such a network and then acting as a usable local access point or relay for personal devices.

The project is still in an exploratory stage. At the moment, I am mainly interested in the required tooling, setup constraints, and the practical viability of such a solution. The appeal of the project lies in the mix of networking, scripting, Linux-based systems, and small-scale hardware integration.

A more technical write-up will follow once I have a stable and reproducible setup worth documenting in detail.




This entry is less a single project in the narrow sense and more an umbrella topic that I keep returning to. It includes questions around personal finance, investing, risk, long-term planning, and the broader logic of financial systems.

Over time I would like to turn this into a more structured collection of notes and tools — potentially including reading notes, small analyses, and practical frameworks for thinking about financial decisions more clearly.

For now, this section remains intentionally compact. It will be expanded once the scope is defined more precisely.




Recently, I started reading scientific publications from different domains more systematically. This section is intended as a place to collect papers that I found interesting, together with short notes or comments on why they matter.


Bitcoin white paper
A future note on the original Bitcoin white paper and why it remains such an influential technical and economic document.
Bat origin of human coronaviruses
Planned reading notes on virology, zoonotic transmission, and the broader scientific context of coronavirus research.
McCulloch and Pitts 1943
A future note on one of the foundational papers in computational neuroscience and the early conceptual roots of artificial neural networks.
Turing Machine
Planned notes on the Turing machine concept and its importance for computation theory, abstraction, and computer science as a whole.


© 2026 www.bojanlukic.com