Hello, I'm
Nikola Siderov.
I'm a young and enthusiastic full-stack software developer with over 5.5 years of experience in building, maintaining and improving applications. I specialize in web-based technologies including .NET, Web API, React, Next.js, JavaScript, TypeScript and many more.
I am consistent, using the latest standards and proven principles in my field. Quality and well-structured software systems are priority for me.
I thrive in both collaborative teams and remote work setups. Based in Plovdiv, I’m ready to deliver impactful solutions.
Work
Full Stack Software Developer
TSD Services • Full-Time • May 2024 - Present
Remote
Working as a full-stack software developer for a client company in the water management industry. The project aims to develop a central monitoring system for various properties and devices, used for real-time tracking and control.
My responsibilities are involved in the development of three web applications:
- React-based client application: Implementation of UI components and features based on detailed UI/UX concepts provided by the design team.
- Angular-based administrative application: Implementation of UI components and features.
- Back-end business logic development, along with building .NET Web API endpoints.
- Contribution and maintenance of the technical documentation.
- Collaboration with team members to ensure seamless development.
Work experience with React, Angular, JavaScript, TypeScript, TailwindCSS & .NET.
Full Stack Software Developer
TSD Software • Full-Time • Dec 2020 - May 2024
Remote
Development and maintenance of an American-based client CRM system in the sales industry using integration with Salesforce and Microsoft Dynamics 365.
Initially, my role was to maintain and develop new features on their existing platforms. However, as the project’s frameworks were outdated and this limited further development, I was tasked to rebuild one of the two platforms using React. This included setting up the project architecture, selecting appropriate third-party libraries, and managing the state efficiently.
Work consists of Dynamics 365 and Salesforce custom development, continuous integration and delivery, Azure cloud administration, SSL certifications management and web platform development using .NET, React, JavaScript, Azure SQL Databases & Entity Framework Core.
Development of a closed company platform - BPM software system designed to include CRM, MIS & any further custom solutions required from the business.
.NET Software Developer
TSD Services • Full-Time • Jun 2019 - Dec 2020
Plovdiv, Bulgaria
Building, maintaining and CI/CD on various internal company and client projects.
Development of a closed company platform - BPM software system designed to include CRM, MIS & any further custom solutions required from the business.
Working with .NET Framework, Azure, Azure AD B2C, ASP.NET MVC, SQL Server, JavaScript, JSON, jQuery, Microsoft Graph.
Education
Software University, SoftUni
Successfully completed several courses in the path of .NET, C#, HTML & CSS, object-oriented programming, SQL, Git and more.
Misc
Sports, Hobbies, etc.
I plan and develop new projects with the idea of improving my technical skills and keeping up with the latest technology trends.
I attend various amateur sports events, mainly short and long-distance running.
I regularly go hiking in the mountain with friends.
I enjoy reading biography and history books when I have the time.
I am a former professional football freestyler with numerous participations in public events and tournaments.
In 2016, I won the Cartoon Network Academy and got the opportunity to travel to London, England to visit Arsenal's youth training center, where we did a training session with Lucas Podolski.
React with TypeScript, TailwindCSS and NextJS web application client with an integration with Sanity.io
bulgarianhistory.com
Building interactive educational history applications using React with TypeScript, TailwindCSS, NextJS web application client with integration for Sanity.io, React Native mobile application development and Adobe Illustrator & After Effects work with custom built scalable vector graphics.
The web application bulgarianhistory.com showcases Bulgaria history through interactive maps with timelines, annotated events, and cultural landmarks. It highlights political changes, population movements, and natural features shaping history. Features include zoom, search, and clickable elements for detailed exploration, supported by citations for accuracy.
Mobile application with React Native is currently under development. You can preview the user interface design attached below or right next to this description.
Adobe Illustrator
The core tool I use to build scalable vector graphics and artwork of historical maps with multi-level layers.
Adobe After Effects
Used for animations, visual effects, and motion picture compositing.
Web Client
Using React as front-end framework to develop sophisticated user interfaces.
Logo Development
The logo design inspired by the Bulgarian Lev, blending national pride with modern aesthetics.
React with JavaScript, Material UI, NextJS web application client with a back-end server side with background workers written in .NET 6. Database integration with SQLite.
Auction System Application
Explanation
This code defines two asynchronous functions, authenticate and renew, which handle user authentication and token renewal using Axios for HTTP requests. The authenticate function sends user credentials to the /authentication/authenticate endpoint, sets a refresh token as a cookie, decodes its expiration time using the jwt-decode library, and stores an access token using a Redux dispatch. If successful, it returns true. The renew function sends a refresh token to the /authentication/renew endpoint to get a new access token and refresh token, follows the same procedure for setting and decoding the tokens, and removes the refresh token cookie if an error occurs, then returns true if successful. Both functions log any errors encountered during the process.
1import axios from "./base/axios";2import cookies from "js-cookie";3import jwt from "jwt-decode";4import { set } from "../context/features/accessTokenSlice";56export const authenticate = async (dispatch, values) => {7 let success = false;89 await axios10 .post("/authentication/authenticate", values)11 .then(function (response) {12 // Set refresh token in cookie13 const decoded = jwt(response.data.refreshToken);14 cookies.set("auth_jwt_refresh_token", response.data.refreshToken, {15 expires: new Date(decoded.exp * 1000),16 });1718 dispatch(set(response.data.accessToken));19 success = true;20 })21 .catch(function (error) {22 console.log(error);23 });2425 return success;26};2728export const renew = async (dispatch, refreshToken) => {29 let success = false;3031 await axios32 .post("/authentication/renew", { value: refreshToken })33 .then(function (response) {34 // Set refresh token in cookie35 const decoded = jwt(response.data.refreshToken);36 cookies.set("auth_jwt_refresh_token", response.data.refreshToken, {37 expires: new Date(decoded.exp * 1000),38 });3940 dispatch(set(response.data.accessToken));41 success = true;42 })43 .catch(function (error) {44 console.log(error);45 cookies.remove("auth_jwt_refresh_token");46 });4748 return success;49};
OrderCollector
Defines an OrderCollector class that extends BackgroundService to periodically process and create orders in a background task. The service uses an ItemService to interact with the database, initialized with a DataContext configured to use SQLite. In the ExecuteAsync method, which runs continuously until a cancellation is requested, the service logs its activity and retrieves items with pending orders. For each pending order, it retrieves the item's bidding history, creates a new order for the highest bid, and stores this order using itemService. It then retrieves all pending orders to notify the relevant parties, pausing for a second between iterations. The ILogger is used for logging information about the service's operations.
1using Data;2using Data.DTOs;3using Infrastructure.Enums;4using Infrastructure.Services;5using Microsoft.EntityFrameworkCore;67namespace Background8{9 public class OrderCollector : BackgroundService10 {11 private readonly ILogger<OrderCollector> _logger;12 private ItemService itemService;1314 public OrderCollector(ILogger<OrderCollector> logger)15 {16 _logger = logger;1718 var optionsBuilder = new DbContextOptionsBuilder<DataContext>();19 optionsBuilder.UseSqlServer(Configuration.DatabaseConnectionString);20 itemService = new ItemService(new DataContext(optionsBuilder.Options));21 }2223 protected override async Task ExecuteAsync(CancellationToken stoppingToken)24 {25 while (!stoppingToken.IsCancellationRequested)26 {27 _logger.LogInformation("Worker running at: {time}", DateTimeOffset.Now);2829 var itemsPendingOrders = itemService.GetItemsPendingOrders();3031 foreach (var itemPendingOrder in itemsPendingOrders)32 {33 var itemHistory = itemService.GetHistory(itemPendingOrder.ID);3435 if (itemHistory.Count() > 0)36 {37 var lastBidding = itemHistory.OrderByDescending(x => x.BidAmount).FirstOrDefault()!;38 var pendingOrder = new Order(lastBidding.UserID, itemPendingOrder.CreatedByID, (int)OrderStatuses.Pending, lastBidding.BidAmount);3940 itemService.CreateOrder(pendingOrder, itemPendingOrder);41 }42 }4344 var pendingOrders = itemService.GetPendingOrders();4546 // notify seller and buyer for created order...4748 await Task.Delay(1000, stoppingToken);49 }50 }51 }52}
Built a web-based auction application with various functionalities and features, such as a real-time bidding system and history, live updates, push notification system, reviewal process and auction sniping software prevention techniques.
.NET based, Blazor & MVC as web clients, consuming from a Web API. Services operating with a custom ORM framework, retrieving data from a SQL Server database.
Home Management System
Custom written mapping layer
Defines a class that extends MapperService and includes method GetCollection<T> to retrieve filtered collection of objects. The GetCollection<T> method takes an expression filter and applies it to fetch data. It identifies the server model type for the generic type T using reflection and dynamically retrieves the appropriate GetObjects method from the BaseFacade. The method then converts the expression filter to a compatible type for the server model using the ConvertExpression method. After filtering the server models, it converts these models back to view models using MapperService.GetViewModelCollection and returns the result as a list of type T. Utilizing reflection extensively to handle generic types and dynamically invoke methods at runtime.
1using APPartment.Data.Server.Base;2using APPartment.ORM.Framework.Declarations;3using System;4using System.Collections.Generic;5using System.Linq;6using System.Linq.Expressions;7using System.Reflection;89namespace APPartment.Infrastructure.Services.Base10{11 public class BaseCRUDService : MapperService12 {13 ...1415 public List<T> GetCollection<T>(Expression<Func<T, bool>> filter)16 where T : class, IBaseObject, new()17 {18 var serverModelType = GetServerModelType<T>();1920 var getObjectsFilteredFunc = typeof(BaseFacade)21 .GetMethods(BindingFlags.Public | BindingFlags.Instance)22 .Where(x => x.Name.Equals(nameof(BaseFacade.GetObjects)))23 .LastOrDefault()24 .MakeGenericMethod(serverModelType);2526 var convertFilterFunc = typeof(MapperService)27 .GetMethods(BindingFlags.NonPublic | BindingFlags.Instance)28 .Where(x => x.Name.Equals(nameof(ConvertExpression)))29 .FirstOrDefault()30 .MakeGenericMethod(typeof(T), serverModelType);3132 var convertedFilter = convertFilterFunc.Invoke(this, new object[] { filter });3334 var serverModels = getObjectsFilteredFunc35 .Invoke(BaseFacade, new object[] { convertedFilter });3637 var toViewModelFunc = typeof(MapperService)38 .GetMethods(BindingFlags.Public | BindingFlags.Instance)39 .Where(x => x.Name.Equals(nameof(MapperService.GetViewModelCollection)))40 .FirstOrDefault()41 .MakeGenericMethod(typeof(T), serverModelType);4243 var result = toViewModelFunc.Invoke(this, new object[] { serverModels }) as List<T>;4445 return result;46 }
Custom written ORM
Defines a DaoContext class that provides data access operations for retrieving objects from a SQL database. The class initializes an ExpressionToSql converter for translating LINQ expressions to SQL queries. A SqlConnection is then established using the default connection string, and a SqlCommand executes the query. The results are read using a SqlDataReader, and while the reader processes the records, it populates the object result with the retrieved data. The method uses generic constraints to ensure that T implements the IBaseObject interface and has a parameterless constructor.
1using System;2using System.Linq;3using System.Linq.Expressions;4using System.Reflection;5using System.Data.SqlClient;6using System.Collections.Generic;7using APPartment.ORM.Framework.Tools;8using APPartment.ORM.Framework.Declarations;9using APPartment.ORM.Framework.Attributes;10using System.ComponentModel.DataAnnotations.Schema;11using APPartment.Common;12using APPartment.ORM.Framework.Enums;1314namespace APPartment.ORM.Framework.Core15{16 public class DaoContext17 {18 private ExpressionToSql expressionToSql;1920 public DaoContext()21 {22 expressionToSql = new ExpressionToSql();23 }2425 public T SelectGetObject<T>(T result, long ID)26 where T : class, IBaseObject, new()27 {28 var table = GetTableName<T>();29 var query = SqlQueryProvider.SelectBusinessObjectByID(table, ID.ToString());3031 using (SqlConnection conn = new SqlConnection(Configuration.DefaultConnectionString))32 using (SqlCommand cmd = new SqlCommand(query, conn))33 {34 conn.Open();35 var reader = cmd.ExecuteReader();3637 while (reader.Read())
At start, Entity Framework Core with code first approach was used, then I migrated to database first, later on EF Core was entirely removed and I developed my own custom object-relational mapping framework.
The project was also initially started with a MVC architecture, with all the business logic implemented in the controller levels. After which, a new Web API project was initialized with a proper business layer where the business logic was migrated. The MVC project send requests to the API and retrieved responses in the form of view-models to display in its views.
This was incomplete and the MVC architecture was redundant, having to support its controllers (only to make calls to the API). I implemented a new web client, under the hood of Blazor, using latest .NET 5. Now, the new web client was dynamic and was just that - a web client, nothing more.
Technical stack built in experience
All of the above-listed images, videos and vectors are actual design recordings of the applications. All maps listed in the Bulgaria history project are made by me using the Adobe ecosystem: Illustrator, Photoshop, etc.
Feel free to contact me via email nikolagsiderov@gmail.com or by messaging me in my LinkedIn page