<![CDATA[Florin Tomozei]]>https://florin.me/https://florin.me/favicon.pngFlorin Tomozeihttps://florin.me/Ghost 5.49Wed, 20 Mar 2024 10:13:04 GMT60<![CDATA[Wolfden Gatekeeper]]>The story so far

At Wolfpack Digital, we are very proud of our office building, located in the heart of Cluj-Napoca, and we worked really hard to make it a cool working space for our pack. We proudly call it the Wolfden, and since last year in the fall, more

]]>
https://florin.me/wolfden-gatekeeper/644b98b6ede95b9f888ef9b6Mon, 08 May 2023 20:01:34 GMTThe story so farWolfden Gatekeeper

At Wolfpack Digital, we are very proud of our office building, located in the heart of Cluj-Napoca, and we worked really hard to make it a cool working space for our pack. We proudly call it the Wolfden, and since last year in the fall, more and more of our colleagues came back to the office to work from here.

Wolfden Gatekeeper
the office

We have some parking spaces in the backyard, and every morning, some of us would come by car to the office. The main gate, which allows car access to the backyard, is controlled by a remote system, that requires you to have a gate remote to open and close it.

Wolfden Gatekeeper
the gate

Pretty soon, we found out that providing remotes to the gate will be difficult, especially since we already gave away all of the remotes that we had in stock. So a quick solution that came naturally was to write on the main Slack channel if someone was at the office and could activate the gate through a remote that we had inside the office.

A couple of months passed, and it became a regular practice in the morning, to have messages arrive on Slack with requests to open the gate. At that moment, this practice became a "low-hanging fruit" of an operation that could be efficiently delegated towards automation.

Here is where the Wolfden GateKeeper enters the scene

On a bleak day in February, I met up with some colleagues for dinner and drinks, and among the various topics that we discussed, was the "eternal" topic of opening the gate. I was inspired to ask: "Couldn't we automate the damn thing?!". We debated strategies and came up with a plan to make it a reality.

A research phase came afterward, reading articles on the Internet about how others managed to do this, and after some time I stumbled upon this article. It was a great inspiration for what we planned afterward.

Raspberry, Dataplicity, Slack API, and some wires

We quickly assembled a shopping list, consisting of a Raspberry PI 3 (the only one in stock, version 4 is quite sought after), an SD Card, a 5V module relay to send the right voltage to the remote, some cables, and the power brick. Additionally, we also added a camera module, but more on that later.

Wolfden Gatekeeper
the shopping list

The plan was simple:

  • connect the remote (somehow, I had no electronics experience beforehand) to the Raspberry
  • create a Slack App that can use a Slash Command to call an endpoint
  • write a software program that will handle the request
  • use Dataplicity to forward the endpoint and make it accessible to the Slack command
  • make sure it's secure

The plan was good. Let's put it into action.

I found a free Saturday in which I could work on this, and have the office to myself, and also a friend that could help me with the electronics part. Decided to write the program in JavaScript, just because I do that all day 😅. And off we went down this rabbit hole.

Began by setting up the Raspberry PI with Raspberry OS, and connected it through the relay module to a remote.

Afterward, I installed Dataplicity on Raspberry and started managing it through their app. They have a great free plan, on which you can connect one device and have total access to it. The Wormhole is remote access through a specific address that they provide and it can expose an HTTP server that will handle requests that come through.

I created a Slack App and a Slash Command from the Admin panel of Slack, called /opendoor, and the cool thing about this is that the payload comes with security headers consisting of a signature and a timestamp, that you can later verify against the App Client ID and Secret.

Then came the code. I wrote a simple Node App that spawns an HTTP server and exposes an endpoint that can handle a Slack Slash Command request. I wanted to make sure that it was secure, so I created multiple checks for the request to make sure that it comes from Slack and that it respects the proper credentials, and only allow it if it came from a particular Slack Channel, so you can trigger the command only from there.

function slackSignatureVerification(req) {
  const signingSecret = 'THE_SECRET';

  const requestSignature = req.headers["x-slack-signature"];
  const requestTimestamp = req.headers["x-slack-request-timestamp"];

  // verify the existance of the X-Slack-Signature and X-Slack-Request-Timestamp headers
  if (!requestSignature || !requestTimestamp) {
    return false;
  }

  // verify if the Timestamp is recent
  if (Math.abs(Math.floor(new Date().getTime() / 1000) - +requestTimestamp) > 300) {
    return false;
  }

  const baseString = `v0:${requestTimestamp}:${req.body}`;
  const cryptoHmacString = crypto.createHmac("sha256", signingSecret).update(baseString, "utf8").digest("hex");
  const expectedSignature = `v0=${cryptoHmacString}`;

  return expectedSignature === requestSignature;
}

The way to verify is described in the Slack API Docs and this article.

I also created a logging system that outputs all of the requests that came through, successful or not, and create a notice when the request parameters were not in order.

Finally, I did a timestamp verification to allow the system to operate only during business hours, and restrict it from operating during the weekend.

const timeRestriction = {
  restrictedTime: {
    lower: 7,
    greater: 19,
  },
  restrictedWeekend: true,
};

const isTimeRestricted = () => {
  const now = new Date();
  const nowHours = now.getHours();
  if (nowHours < timeRestriction.restrictedTime.lower || nowHours > timeRestriction.restrictedTime.greater) {
    return true;
  }

  const nowDay = now.getDay();
  if (timeRestriction.restrictedWeekend && (nowDay === 0 || nowDay === 6)) {
    return true;
  }
  return false;
};

If all the checks are passing, we will open the relay module for one second with the help of the onoff library.

const PINX = new Gpio("PIN_NUMBER", "out");
let relayOpen = false;

PINX.writeSync(0);
setTimeout(() => {
  PINX.writeSync(1);
  relayOpen = false;
}, doorTimeout);

Tying everything together, it was time to test the newly born Wolfden Gatekeeper. And hold and behold, it's ALIVEEE!

0:00
/
the first test

Final thoughts

This was a great learning opportunity for me, both by learning how to use a Raspberry and some new info about electronics, and it was also a neat side-project on which I got to write some code.

I am already thinking of future improvements, and one of them will involve a camera module that will take a picture of the gate, and use a simple background subtraction algorithm to detect if the gate is opened or closed, to be able to close it after working hours, in case it remained open.

If you got this far, thank you for reading and I'll see you in the next one.

over and out.

]]>
<![CDATA[Hiking on the coast of Portugal - Fisherman's Trail]]>In the month of March, right after my birthday and my pseudo-mid-life-crysis-turning-thirty-moment, I decided to go on a 4-day hike in the beautiful country of Portugal. The plan was to follow The Fisherman's Trail (Trilho dos Pescadores), starting in Sagres and ending up ... well, ending up as far

]]>
https://florin.me/hiking-on-the-coast-of-portugal-fishermans-trail/645517700abb574dfc4493fdFri, 05 May 2023 17:00:07 GMT

In the month of March, right after my birthday and my pseudo-mid-life-crysis-turning-thirty-moment, I decided to go on a 4-day hike in the beautiful country of Portugal. The plan was to follow The Fisherman's Trail (Trilho dos Pescadores), starting in Sagres and ending up ... well, ending up as far along the trail as possible.

Day 1

Trail map

After packing up my backpack, I went to the train station in Faro and took a train to Lagos, along with a bus that took me near Sagres, at Cabo de São Vicente. Getting there, I was greeted by the lighthouse that marks the most southwestern point of Europe. From there on, my means of transportation would resume to my trail runners and sandals, powered by my two amazing feet. 🤪

Going along the coast, I traveled around 15 km until Vila do Bispo, getting there around 6 PM in the evening. The first task was to find a place to sleep for the night, so thus the quest began. After trying multiple locations, some of them being very out of my budget, I had the good fortune to bump into two young locals who spoke English proficiently. They recommended that I try a surf house/hostel (GoodFeeling - Hostel & Guesthouse) in the nearest town of Raposeira which seemed very price-friendly. I gave them a call and they assured me that they have an extra bed, and I told them that I would arrive in the following hour. They assured me that I would only pay them 22 coins of currency (euros), and I was delighted to hear that.

With a quick pit stop at the local Lidl, I supplied my pantry with food for that night and walked about 2 km to the surf house. There I was greeted by the most welcoming people that I've seen in a while, and they took me on a tour, presenting the bunk beds, bathrooms, kitchen, and backyard (they also have a pool, wink-wink). Took my dinner on the backyard porch, the first of many consisting of sardines, an apple, a carrot, and some pastry, together with some kefir. And to finish it off, two beers.

At around 12 PM I was in my bunkbed, getting some most needed shuteye.

Day 2

Trail map

Just as the early bird gets the worm, I woke up at around 7 AM, did some morning stretching in front of the pool and, after packing my stuff, I was on my way to the next part of the trail. With a quick refill at the trusted Lidl, I decided to supply the pantry with things for two days, since I didn't know what I might find at the destination. Short pit stop at a local coffee shop, getting the breakfast of Portuguese champions, an expresso, and pastel de nata.

Let the hike begin. This one was a long one, around 20 km, and I can say that this is the moment when the coast started to reveal all of its beauty to me. The elevation was increased, with around 500m of ups and downs, a bit of fog, and beautiful scenery, that blew me away.

Towards the end, a great big hill was standing before me, blocking my view of the ocean. Taking a deep breath, I started the climb, and upon reaching the peak, the view opened, giving me a breathtaking view of the ocean. I was stunned, marveling at the wonder of the waves crashing along the cliffs, moving without care towards their end, and subduing back to form the next wave. I needed a moment then, and took more than 20 minutes to just sit there and take in the view.

Hiking on the coast of Portugal - Fisherman's Trail
the breathtaking view

With the rest of the energy that I had left, I finished the trail in the town of Carrapateira, and started the quest of the day, to find a resting place for my bones. With the help of Google Maps, I scoured the available sleeping places, going first to Carrapateria Lodge and asking the landlady for an offer. She told me that it would be 35 euros, and I thanked her kindly, with the purpose of visiting the other places and also asking for their offers. I was remiss when they told me higher prices, so I returned to the landlady, and struck a bargain using my amazing charisma skills, reaching a final price of 30 euros.

She presented me with my room and the facilities, and I got to take a much-needed shower.

Being a Sunday, everything was closed, except for the local bar from which I was able to purchase two bottles of purified ale. Looking at the map, I saw a beautiful coastline location, where I decided to eat my dinner and enjoy the view. I was not disappointed in the least. The waves were crashing, the food provided sustenance, and the beer was cold and revigorating.

Upon finishing my dinner and drinks, the sky decided to throw a wonderful show for me, with amazing colors of deep red, orange, pink, and purple. I was stunned once again.

Hiking on the coast of Portugal - Fisherman's Trail

Took a short hike in the dusk and night, circling the coastline and getting back to the city for a good night's sleep. Around 10 PM I was knocked out cold, recovering for the next day.

Day 3

Trail map

Started the day at 7:30 AM, with breakfast and coffee from the local bar, and hopped back on the trail to my next destination. Here is where the sand started to cover the trail mostly, so I had to switch gears and put on my "cauciucuri de vară", the sandals. The coastline was my friend for about half of the trail, after which I went inwards a bit, changing the scenery of the ocean for forests and sand.

After a long portion of the forest, the ocean came back to me, and I was greeted by a stony beach with smooth waves and cloudy skies.

Hiking on the coast of Portugal - Fisherman's Trail
the stony beach

The town of Arrifana was on the other side of the cliff, with a steep descent, and beautiful houses hanging on cliffs. Everything was expensive here, and I started to feel for the first time that I might fail my quest for accommodation. My luck came at the last house that I thought of visiting, which was in renovation, and the owner, that was also working at the house, recommended that I try the Arrifana Destination Hostel. Yet another surfer hostel, which also had an in-house bar and restaurant. Their price was very reasonable, offering me a bunkbed room, shower, and other facilities for the wonderful price of 22 coins of currency. I was most pleased, and after taking a hot shower, I was off to explore the town and delight in my packed dinner, to which I added a wheel of cheese. Since most bars and restaurants were open, I purchased multiple draughts of ale and enjoyed them alongside another stunning sunset (and a cat).

Back at the hostel, I explored a bit the hallways and found some beautiful art made out of recycled plastic, that was "rescued" from the ocean.

With the little energy that I had left, I joined the other travelers in the local tavern and got some time to scribble some thoughts in my journal. 9 PM o'clock finds me in bed, ready to depart to dreamland.

Day 4

Trail map

Final day. Leaving Arrifana and taking the trail along the coast (yea, again, I kno'), more sand, more sandals, hot scorching sun, and smooth breezes that blessed my skin with a much-needed tan.

Finished the trail after another 17 km, reaching the town of Aljezur. Found the fancy coffee shop of the town and enjoyed a much-needed flat white, after which the final quest began: find a way to get to Lagos in time, to catch the train leaving at 18 PM. Borrowing a marker pen from the coffee shop, I scribbled Lagos on a piece of paper and went to a road curb to try to hitch a ride. After 20 minutes and about two years of the pandemic, I was starting to think that hitchhiking was a practice of the past, but right before I could give up, a lovely couple from NYC stopped in front of me and offered me the back seat. We talked a lot about every topic conceivable, from politics and the healthcare systems of America and European countries to jobs, life, and everything related to it. They were lovely and the husband told me that his entire childhood he hitchhiked the long roads of America, getting from one place to the next. Upon reaching Lagos, I had to delight myself with a much-earned burger and some beers.

Getting to the train station, I was informed of the fact that my 18 o'clock train was subject to the ongoing strike, and my only option was the later one, from 20 PM. No problem there, just enough time for another couple of beers and some journaling. Hopped on the train and by 22 PM I was back in Faro. And thus the adventure was finalized.

In conclusion

Trilho dos Pescadores is a wonderful experience, especially in the off-season of March, when the temperature allows for an amazing experience. My key takeaways here would be the following:

  • have a pair of trekkers
  • have a pair of sandals
  • change them as soon as the terrain changes
  • buy food in anticipation, since you don't know what you might find at the destination
  • sunscreen. a lot of it
  • wear a hat
  • and other means of protection for the skin
  • you will always find a place to sleep, you just need to search for it
  • a camelback helps a lot
  • food is pretty cheap, especially from the convenience stores
  • download the maps from here
  • you can walk the trail alone
  • together with friends, it might be even cooler
  • just enjoy the moment. no headphones, turn off the internet
  • and don't rush it. soak it in. It's worth it

Finally, here are my stats from the 4-day trail that I took.

Hiking on the coast of Portugal - Fisherman's Trail

If you managed to reach this paragraph and enjoyed the read, feel free to share it or send it to a friend. And if you decide to take the trail, give me a ping. I would love to learn about your experience.

]]>
<![CDATA[Ghost: the story of my blog]]>https://florin.me/ghost-the-story-of-my-blog/642949483bc2ea25f2b56351Sun, 02 Apr 2023 10:37:25 GMT

I wanted to write this article for some time now, telling you the story of how I started this blog, how it was built at first on WordPress, then migrated to Ghost, and finally how I managed to host it for free on Netlify.


The domain

I think it was in 2016 that I learned about the GitHub Student Pack offer, which I recommend to this day for every student that dabbles in the forbidden arts of programming. One of the offers from the pack is 1 year domain name registration on the .me TLD.

So I signed up with my UBB email at that time and went to Namecheap to verify some domain names that might be available. To my surprise, no one named Florin got there before .me, so I was able to secure the www.florin.me domain.

At first, I do believe that it was simply a index.html file that was hosted somewhere, but pretty soon I got a DigitalOcean droplet for 5$ and managed to FTP into it and upload a WordPress installation.


In the beginning, there was WordPress

Personally, I have a complicated relationship with WordPress. I love it, and then I hate it, and then I love it again. It's a great CMS (Content Management System) tool, and since it has PHP at the core, its extensibility is really on point. You can add any theme you want, and every functionality you can think of, by means of Plugins, and of course, you can write your own code. But since it is so extensible, it is really easy to get to a point where everything is so bloated and twisted, that you don't know what is causing the problems that arise.

So, in the beginning, there was WordPress, mainly because all of the scout websites were also using WordPress. I mention this because when I created my blog, I was the IT&C Commissioner for the National Organization of Romanian Scouts.


Then, he met his Ghost

And then I heard about Ghost CMS. And when I hear about cool things, I immediately become a fanboy. That's all that you can hear me talk about. This was also the case.  

I really liked that it came with a CLI. And since the terminal was the place where I lived, it came naturally to start a new Ghost Website with:

sudo npm install -g ghost-cli@latest
cd ~/Projects/ghost-blog
ghost install local

And if a new version of the CMS came out, you would simply:

npm install -g ghost-cli@latest

It also has a great community. Free templates. Easy to migrate from a lot of other CMS's. A roadmap and new features that are shipped constantly. Email newsletter generation. Member management and member tiers.  Integrated directly with Stripe.

But the big selling point was JavaScript. Because it made it really fast (compared to old WordPress PHP). And it was also kinda beautiful. The themes were clean and responsive and with a lot of negative space. The admin was simple and intuitive, with only a couple of areas that you could manage. And finally, the writing experience. Here it is (sorry for the text inception):

Ghost: the story of my blog

It's simple. Clean. Without distractions. Settings and other metadata about the article are hidden behind the sidebar button in the top right corner. A minimal word counter in the bottom right corner. And that's it. For me, it was exactly what I was looking for: a blank page that I can fill, press Publish and it was live.

And you can check out the admin for yourself, on this Live Demo:

Ghost Admin
https://play-with-ghost.com/
💡
Admin panel credentials:
relations@firepress.org
firepress1

Discovering SSG websites

I always thought about websites that had a CMS, as something that needs to be on the server side. You need to have a database where you hold the data, a web server that also handles assets, etc. But then I learned Nuxt and found out about its Static Site Generation feature (SSG for short).

And then I wondered... could I have a "build" step to my website, in which I can generate a static version of it, while still handling all of the content creation inside the Ghost Admin?


Converting to a static site

So this is what I did. Exported the data from the Ghost installation that was in the cloud. Did a local setup of Ghost, imported the data, and uploaded the theme that I was using then.  Downloaded the images and moved them inside content/images. Created a repository on the local installation and tied it up to my GitHub. Then ignored some folders that were relevant only to the installation, such as:

versions/**/node_modules
current
static
content/logs
.ghostpid
versions
.gitignore

The tool that allows the magic to happen is ghost-static-site-generator.

# it needs wget
brew install wget

# add gsgg
npm install -g ghost-static-site-generator

Inside the package.json file I added a script to generate the static website:

{
  ...
    "scripts": {
        "generate": "gssg --url https://florin.me --productionDomain https://florin.me"
      },
  ...
}
package.json

And finally, when running yarn generate it will export all of the website pages to the static folder. I simply cd ./static and initialize a new repository, that has the static version of the site. Push that to GitHub and tie it up with Netlify. Wait, when did we get from DigitalOcean to Netlify?


From DigitalOcean to Netlify

Ok, so the droplet was 5$ a month. That's 60$ per year or 270 RoN. Not much, but what if I could save all that money, and pay nothing for hosting it? Netlify has a great offer for its Free Tier, with 100GB / month Bandwidth Usage. DNS management. And really good integration with GitHub, with preview deployments and all that razzle dazzle.

So it was as simple as Login with GitHub inside Netlify, creating a new project, and selecting the static repository created earlier. And in less than a minute, the website is live, hosted statically, with 0$ to spend. That looks like a good deal.

Going back to Namecheap and changing the nameservers to the Netlify ones, and we are live, baby!


But in the end, it doesn't even matter

This was my story, and if you got here, I do hope that you enjoyed the read and all the acronyms 🤪. If you also have a WordPress installation and are looking for something new and fresh, or you really liked how the Ghost Admin looks, please, by all means, give it a try. I guarantee that you won't regret it.

And if you want to spread some love, consider sharing this article with your community.

Cheers! 🧙🏻‍♂️🚀

]]>
<![CDATA[How to easily write a website]]>https://florin.me/how-to-easily-write-a-website/6408f4ca7eaab085454beaa7Wed, 08 Mar 2023 21:39:17 GMT

OK, so hopefully I caught your eye with this catchy title. And I want to underline the word easily because this operation can be done in under 20 minutes, with a fully working website that you can show to others and boast about. 🤪

I also want to mention that this article is targeted at people that have zero knowledge of programming, and that want to have a webpage where they present their stuff like projects or ideas, write blog posts, or any kind of content that could benefit from being made public.

Also, for students that want to create their Curriculum Vitae and host it somewhere online, this is the article for you.

Finally, did I mention that it's totally free?!


Creating a GitHub Account

This one should be pretty straightforward. You go to the Signup Page of GitHub and create an account. They will ask you for your email and password, and finally, they will ask you to input a username. A good idea here is to use your name, written together or with a hyphen. For example, florintomozei or florin-tomozei. This is important, because later when we are going to create the repository for your website, we will use your username for its name.


Creating our first repository

Ok, I know the word repository is confusing, but let me quickly explain the term. Simply put, a repository is a folder with files in it, on which Git does something called version tracking. Meaning it will track all changes that you make to those files. A good example of this sort of tracking is in Google Docs, when you click on Version History and it shows you all the changes made by you and other people to the document (image below).

How to easily write a website

So, let's create our first repository. 🤩

For the first repository, you will need to find a green button called New and click on it. When logged in and on the homepage of github.com, it should be on the left side of the screen. Something like this:

How to easily write a website
Try to find the green New button

Good, now we need to give it a name, in the Repository name input field. Here is where we need to use your username, in the format of:

<your-username>.github.io

So, for example, my username is Mallfurion (yea, I know...) so my repository name will be mallfurion.github.io. If your username is gheorghe-hagi, the repository name will be gheorghe-hagi.github.io. Easy peasy, lemon squeezy.

Leave all the other settings as default, and click the green button Create repository.


Let's add some files

On the repository page, there will be an action for creating a new file. Click on that.

How to easily write a website

First of all, we will need a configuration file, to let GitHub Pages know some setup details. This first file we will call _config.yml.

For _config.yml, paste the following code and replace the title, author, and description with your own:

theme: minima

title: Your website title
author: Gheorghe Hagi
description: Professional footballer, retired

header_pages:
  - index.md

When done, click the green button Commit Changes ...


Getting familiar with Markdown

Ok, so now we need to do a bit of learning. Don't worry, I won't insist too much, you can get familiar with all of the Markdown syntax later. You might be wondering, "WTF is Markdown?"

Simply put, it's a markup language that allows you to write formatted text in plain text. Here you can find a very helpful cheat sheet, but for what is worth, here is a quick intro.

# This will render to a Heading 1
## This to a Heading 2
### This to a Heading 3, and so on

*this is italic*
**this is bold**
~~this is strikethrough~~

[This is a link](https://florin.me)
![This is a beautiful image](https://florin.me/logo.png)

Here we have some `inline code`.

``` 
This is a block of code.
```

After this line, we will have a horizontal line.
---

Creating our index page

After we added the _config.yml, we should be on the homepage of the repo (that's short for repository). At the top, we should see a dropdown button called Add file ▼, click it, and select ➕ Create new file.

Let's name it index.md, and add some information to it:

---
title: Home
description: welcome to my website
---

## Hello there, beautiful people!

Lorem ipsum dolor sit amet, consectetur adipiscing elit. 
Proin et dui turpis. 
Quisque dui velit, condimentum eget commodo eu, posuere ut tortor. 
Fusce vulputate est a condimentum semper. 
Integer ex ex, suscipit at elit at, mollis pulvinar nunc. 

---

## My name is Gheorghe Hagi

Mauris fringilla odio tristique, consectetur est vel, laoreet tellus.
Suspendisse at nibh id lacus lacinia rutrum. 
Nulla pharetra mi massa, vel egestas tellus auctor sit amet. 
Aliquam sit amet massa interdum est rutrum rutrum. 
Donec a diam a lorem commodo auctor.

You can replace the placeholder text with a cool description about you! 🤪


Finally, let's set up GitHub Pages

This is the final step, I promise. We need to go to Settings, click on Pages in the left menu, and select a Branch from which to deploy. For our use case, that will be the main branch.

How to easily write a website

And off it goes to the Internets

The GitHub Pages will build your website, and you can see the progress of that under the Actions tab of your repository. It usually takes about a minute. To easily access your GitHub Pages URL, let's add it to the repo's description.

Inside the main page of the repo, click the cog wheel ⚙️ near About, on the right, and check the box for ✅ Use your GitHub Pages website. Press Save Changes.

Now if you click the URL that appears under the description, you should be able to see your new webpage! Congratulations, you did it!  🥳 🎉 🎊

Advanced: Add pages, images, and styles to your website

I couldn't leave you with only one page full of text, now could I?

To add images, you will create an assets folder, then an images folder, and add your images there. When adding files in the GitHub interface, in order to add folders, you will provide a slash after the name of the folder, to create that particular path. So in our case, in order to to create that particular path, we will type in:

assets/images/.gitkeep

That .gitkeep is just an empty file so that GitHub can create the folder structure. You can delete it after you upload an image, if you want to. To upload an image, select from the Add file ▼ dropdown the Upload files option, then choose the image file you want to upload.


Inside the .md pages, you can reference an image like this:

![description of banner](/assets/images/banner.png)

The same thing can be done for documents, PDFs for example:

[Download PDF](/assets/docs/cv.pdf)

Links are added this way:

[GitHub](https://github.com/Mallfurion)

To add more pages, a good idea is to structure them under a folder, called pages. You can also add them to the root of the project, but we are not savages, are we?!


Finally, we can add some styling to our webpage. To do that, we will create a file called main.scss under the assets folder. It has to start with the two lines at the top and the minima import:

---
---

body {
  margin: auto;
}

@import "minima";

hr {
  margin: 3rem 0;
}

h2 {
  font-weight: bold;
  margin-bottom: 2rem;
}

Don't forget to commit the files, and you are golden. Images, styles, and a whole lot of HTML magic can happen on your website. The sky is the limit!


My GitHub Pages website

If you are stuck on any step or want to have a visual representation of the repository, you can check my GitHub repository.

GitHub - Mallfurion/mallfurion.github.io
Contribute to Mallfurion/mallfurion.github.io development by creating an account on GitHub.
How to easily write a website
Home
welcome to my website
How to easily write a website

Bonus: Creating your CV

Also, I wanted to share a cool app that allows you to create and save your CV easily, I've been using it for quite some time and it helped me a lot in keeping my CV up to date. Give it a check over here. You submit your data to the various categories and can download it as PDF and JSON (JSON just in case the app will disappear in the future, you can have your data saved 😜).


I do hope that this was helpful for some of you, and if you got to this part, I want to thank you for the read.

If you will implement a GitHub Pages of your own, please let me know with a comment.

Good luck and keep on coding! ❤️

]]>
<![CDATA[Things I've learned programming]]>A bit of a backstory

Have been doing this craft for some time right now. I do remember the first lines of code that I've written at 14, in C++, #include stdio.h . I remember the first SQL queries that I've written at 16. At the

]]>
https://florin.me/things-ive-learned-programming/62b1b2704e5c6972e4e8f58dFri, 17 Jun 2022 15:24:46 GMTA bit of a backstory
Things I've learned programming

Have been doing this craft for some time right now. I do remember the first lines of code that I've written at 14, in C++, #include stdio.h . I remember the first SQL queries that I've written at 16. At the same time writing C++ and Lua scripts for the Trinity Core emulators, fixing bugs for the Illidan encounter in Black Temple. Doing SysAdmin magic for Moodle. F#ucking up a "deploy" because, in the FTP client, I've pulled the files from right to left, overwriting everything I did locally. Trying to code and run an Android project alongside a device emulator with only 1 GB of RAM in 2013, during my Erasmus mobility.

Writing my first lines of JavaScript and just falling in love with the ease of producing something visual, that can be accessed by anyone with a browser. Discovering Angular. Falling in love again with Python and Django during my internship. Using them to develop the management application for the 2017 RoJAM event. Going from hate to love with Type Systems and especially TypeScript.

Up to today, when I still find new and exciting things, like Vue or Nuxt. Or (I've been today years old) when I learned that you also can call super() in methods, not only inside the constructor.

So I decided to craft a list of things that I've learned along this awesome journey, that I would really like to revise in 10 years and see what I can add or withdraw.


10 things that I've learned programming


  1. Read code. Especially well-written code. A good place is the open-source projects or frameworks, that usually have good abstractions or DP (design pattern) implementations.
  2. Learn multiple languages. The first one is hard, the second one is tough, but then it gets better. Each language has its special "flavor" regarding paradigms and principles, and by knowing multiple languages in which you can express yourself, you will certainly become a better coder.
  3. Code design patterns. Replicate framework functionality. Write algorithms. Make them efficient.
  4. Try to understand the entire system, not just your small part. Know about databases. Understand CSS Layouts. Get insight into how caching works. Learn about async and notifications. It helps a lot to have a broad horizontal development of knowledge.
  5. Have side projects. Express your ideas in code. And don't be afraid to create that fun app that you've always wanted.
  6. Subscribe to a newsletter that gives you recurrent updates from the community.
  7. Don't be afraid to refactor.
  8. Try to get introduced to a type system. It will help with the previous point, and a whole lot more.
  9. If you have a problem that you can't solve today, sleep on it. The right solution will usually come in the morning, and it will take a lot less time.
  10. Try to give back if you can. Join a community. Contribute to an open-source project that you use and enjoy. Teach others. Volunteer. Raise awareness. Or simply talk about the new things that you learn.

If you got to here, thank you.

]]>
<![CDATA[Război.]]>De câteva zile încoace, întreaga lume și-a scos popcornul din microunde, s-a pus confortabil pe canapea și cu telecomanda în mână schimbă posturile de media, într-un consum feroce de informații și update-uri despre invazia ș

]]>
https://florin.me/razboi/62b1b2704e5c6972e4e8f58cSat, 05 Mar 2022 13:22:48 GMT

De câteva zile încoace, întreaga lume și-a scos popcornul din microunde, s-a pus confortabil pe canapea și cu telecomanda în mână schimbă posturile de media, într-un consum feroce de informații și update-uri despre invazia și genocidul lui Putin.

Cei mai curajoși dintre noi s-au mobilizat, au mers la graniță, au servit voluntar pentru cei care în momentul de față fug din calea pericolului (și au privilegiul să poată să treacă o graniță), au făcut ceai și sandwich-uri, au adunat haine și conserve, au făcut plinul de mai multe ori și au mutat mobilă prin casă ca să facă loc de saltele și paturi mobile.

Eroi în ochii mei. Iar apoi treci cu gândul granița și ajungi lângă Nipru, unde eroii poartă arma in piept și cele două dungi, una albastră și una galbenă, pe braț. Sunt oameni la fel ca și noi (cei care pot să stea la căldură și adăpost). Sunt actori. Sunt boxeri. Sunt ITști. Sunt cântăreți. Sunt medici. Profesori. Barmani. Instalatori. Antreprenori. Oameni pe care în orice altă zi, i-aș putea confunda cu vecinii mei sau cu bunii mei prieteni. Iar ei, în acest moment, sunt pe străzile orașelor, cu arma în mână. Cu lansatorul de rachetă pe umăr. Cu targa pe care burdușești două cadavre. Cu ultima pereche de șosete curată în picioare, pe care ai luat-o acum 8 zile.

Oamenii ăștia se află la 900 de kilometrii de mine. Dar de 8 zile încoace mă tot întreb, cum ar fi dacă oamenii ăștia ar fi la 900 de metri de mine, sau 900 de milimetri? Dacă ar trebui de mâine să îmi beau cafeaua în tranșeu, să țin arma pe piept și să visez la o supă caldă și o pereche de chiloți curată?

Cum ar fi dacă eu ar trebui să îmi feresc capul după ce un glonț a ricoșat din casca și așa îmbătrânită pe care am primit-o de la cazarma Diviziei 4 Infanterie ”Gemina”? Dacă trebuie să fug din calea clădirii care urmează să se așterne pe asfaltul pe care stăteam eu cu 10 secunde înainte? Să trebuiască să îmi stăvilesc lacrimile și urletele de neputință în timp ce car trupul neînsuflețit a unui bun prieten, care a primit și el vesta anti-glonț la 45 de secunde după ce am luat-o eu pe mine?

O să pot să trag în ei?

O să pot să îi privesc după ce cad pe jos fără suflare, să mă duc să le închid ochii pentru totdeauna?

O să fiu eu împlinit și mulțumit în ultimile 2 minute pe care o să le trăiesc, după ce cele 3 gloanțe mi-au evitat gațios plăcile de kevlar?

Mă trezesc din vis și scutur din cap de 3 ori, ca să treacă visul urât. Știu că e foarte improbabil să ajung acolo, dar doamne ce gând oribil și rece. Dar dacă ar fi cazul, aș ridica arma de jos și mi-aș pune-o în piept, din cauza actorilor, boxerilor și cântăreților ăștia. Exemplele din ultimile zile de umanitate, eroism și curaj mă fac să am încredere în oameni. Exemplele de unitate și suport mă fac să am încredere în instituțiile europene și visul european. Și toată istoria mă învață cu nebunii cu un fixism determinat nu rezistă foarte mult pe lumea asta, iar Vova s-ar putea să nu prindă tortul cu 70 de lumânări.

Război.
pawns topple the King

Orice s-ar întâmpla, viața merge înainte, și așa cum zice Lucian, trebuie să ne vedem de treabă. Să nu lăsăm povara asta să ne îndoaie și mai tare de spate, să nu umblăm cu capul plecat și cu ochii în pământ. Să fim oameni, cu noi înșine și cu toți cei din jur.


Inspirația mea pentru zilele astea negre


Andriy Khlyvnyuk, vocalistul trupei Boombox, s-a întors din turneul din US ca să pună arma în piept. (vid 1, feat Kiffness)

Antytila trebuiau să prezinte noul album la radio și televizor, dar au trebuit să își pună arma în piept. (vid2)

Yarmak își așteaptă uniforma și pușca în biroul de înrolare militară. (vid3)

Mykhailo Fedorov, ministrul Digitalizării, și tot ce o reușit el să facă cu un pix, o ștampilă și un cont de Twitter.

Frații Klitschko, care au fost în vizită la oamenii din metrou și au făcut selfie-uri cu ei și cu cățelul.

A my nashu slavnu Ukrayinu, hey-hey, rozveselymo!

Slava Ukraini!
Heroiam slava!
]]>
<![CDATA[Juggling session | 01.07.21]]>With Brumbi, Ana and Emi.

]]>
https://florin.me/juggling-session-01-07-21/62b1b2704e5c6972e4e8f58aThu, 08 Jul 2021 12:23:11 GMT

With Brumbi, Ana and Emi.

Juggling session | 01.07.21
]]>
<![CDATA[Relaxare în Maramureș]]>A mai trecut o Adunare Generală, pe care am bifat-o cu succes pe partea de vot online, cu tot cu raportări și mail-uri de confirmare a voturilor. Duminică seara, calendarul îmi arăta o săptămână î

]]>
https://florin.me/relaxare-in-maramures/62b1b2704e5c6972e4e8f589Tue, 27 Apr 2021 15:22:26 GMT

A mai trecut o Adunare Generală, pe care am bifat-o cu succes pe partea de vot online, cu tot cu raportări și mail-uri de confirmare a voturilor. Duminică seara, calendarul îmi arăta o săptămână întreagă de conced, iar pe AirBnB aveam o rezervare la Casa Valea Vinului, de luni pe vineri.

Zorii zilei de luni mă prind la volan, la cea de-a 3-a sesiune de condus cu instructorul, unde am mierlit-o binișor la niște intersecții și un sens giratoriu. Până la urmă i-am dat de cap, cică întorc volanul destul de bine, dar cu ambreajul încă port o luptă titanică (în sesiunea 4 am reușit să îl țin mai bine în frâu). Termin cu condusul și am timp exact cât să mănânc și să pregătesc bagajul.

Mă pregătesc să plec de acasă, îmi iau rămas bun de la plante și de la laptop (laptop-ul îmi aruncă niște priviri triste, pe sistemul ”da pe mine de ce numă iei?!”, îi zic că așa am decis de săptămâna trecută; el răsuflă a înfrângere), închid ușa și la gară cu noi!

Ne urcăm în Regio 4110, găsim compartiment gol. 5 ore trec ca nevăzute, cu povești și un mail care tot nu intră. Apăs pe trăgaci de câteva ori. Ana apasă și ea.

Ajungem în gară, Vișeul de Jos. Grecu ne așteaptă lângă peron, urcăm bagajele în portbagaj și în douăș de minute suntem sus pe deal, la căsuța din povești.

Chiar e din povești, casă bătrânească restaurată exemplar, cu tot ce ai nevoie, de la baie cu duș, bucătărie cu frigider, plită, oale și vase de poți să ți un MasterCh(i)ef, cuptor cu microunde (și popcorn surpriză). Iar apoi, camera de somn, cu sobă și televizor plat. Poți să îți dorești mai mult?!

Și o prispă din povești, numa bună de prânzul împreună cu câinele, sau de stat la citit, împreună cu pisica.

Relaxare în Maramureș
la citit.

Tot ce a urmat a fost o relaxare de vis.

Poteci bătute de bocanci.

Relaxare în Maramureș
04MB01: Vişeu de Sus - Valea Peştilor - Vişeu de Sus

Poze la căprițe.

Picnic în lan de flori pe marginea drumului.

Hamac atârnat de copacii care se legănau în bătaia vântului, așteptând furtuna.

Foc la sobă, pentru încălzit picioarele și uscat geaca atinsă de ploaie.

Relaxare în Maramureș

După-amiezi leneșe, ascultând ploaia.

Pahar de vin cu paste, la lumina lumânării.

Pe scurt, am fost să ne relaxăm.

Eu zic că ne-a ieșit destul de bine. Casa lui Radu este de milioane, o recomand din suflet la cei care își doresc o relaxare bine meritată, sus pe deal, la liniște, cu păsărele ciripind și ropot de ploaie lin pe fundal la un film de Netflix.

Ne-am despărțit cu greu de căsuță, am promis că ne mai întoarcem atunci când zgomotul orașului o să vrea să fie înlocuit cu liniște de Maramureș. Grecu ne-a lăsat la gară, unde o venit și mail-ul mult prea așteptat, iar Regio 4114 ne-a condus până în gara din Cluj, alături de un apus superb.

Relaxare în Maramureș
apus din tren.

Până data viitoare (am promis că o să scriu mai mult, sper să-mi și iasă).

]]>
<![CDATA[Retez@t la picior | 12 - 13 decembrie 2020]]>

The Album

Retez@t la picior | decembrie 2020
45 new photos added to shared album
]]>
https://florin.me/retez-t-la-picior-12-13-decembrie-2020/62b1b2704e5c6972e4e8f586Sun, 13 Dec 2020 00:00:00 GMT

The Album

Retez@t la picior | decembrie 2020
45 new photos added to shared album
Retez@t la picior | 12 - 13 decembrie 2020
]]>
<![CDATA[Escapadă în Ciucaș | 1 decembrie 2020]]>

The Album

Escapadă în Ciucaș | 1 dec 2020
55 new photos added to shared album
]]>
https://florin.me/escapada-in-ciucas/62b1b2704e5c6972e4e8f585Tue, 01 Dec 2020 00:00:00 GMT

The Album

Escapadă în Ciucaș | 1 dec 2020
55 new photos added to shared album
Escapadă în Ciucaș | 1 decembrie 2020
]]>
<![CDATA[Conced în D'letea și imprejurimi | 14 - 20 septembrie 2020]]>

The Album

Conced în D’letea și imprejurimi | 2020
84 new photos added to shared album
]]>
https://florin.me/conced-in-dletea-si-imprejurimi-14-20-septembrie-2020/62b1b2704e5c6972e4e8f584Sun, 20 Sep 2020 00:00:00 GMT

The Album

Conced în D’letea și imprejurimi | 2020
84 new photos added to shared album
Conced în D'letea și imprejurimi | 14 - 20 septembrie 2020
]]>
<![CDATA[Conced' 2020 | 17 - 23 august 2020]]>

The Album

Conced 2020 (Florin)
100 new photos added to shared album
]]>
https://florin.me/conced-2020/62b1b2704e5c6972e4e8f583Sun, 23 Aug 2020 00:00:00 GMT

The Album

Conced 2020 (Florin)
100 new photos added to shared album
Conced' 2020 | 17 - 23 august 2020
]]>
<![CDATA[Today was about scouting | Adunarea Generală Scouts Cluj 2020]]>Today was about scouting.

Taking up the challenge, a couple of months ago, to become one of the strategic coordinators for my beloved organization was a real step-up from what I was normally doing for the scouts. Even though I might’ve had my skepticism at that time, it

]]>
https://florin.me/today-was-about-scouting/62b1b2704e5c6972e4e8f560Sat, 07 Mar 2020 00:00:00 GMTToday was about scouting.Today was about scouting | Adunarea Generală Scouts Cluj 2020

Taking up the challenge, a couple of months ago, to become one of the strategic coordinators for my beloved organization was a real step-up from what I was normally doing for the scouts. Even though I might’ve had my skepticism at that time, it turned out that I might bring some knowledge to the table and actually be useful, beside tapping away at the keyboard, writing code.

So the day started by participating at the National Board meeting, presenting the first report ever written (formally) for a national team. It was a pleasure to be there and talk about what we did so far and the concrete actions that we plan to do with the TECH team in the near future.

Afterwards, I ran to the General Assembly of the local scout center of Cluj-Napoca (Scouts Cluj) where we voted together for the next Local Council, that will govern the local center for the next three years. It was a great atmosphere, filled with great plans for the future and pragmatic thinking for the obstacles that we face currently. I am looking forward with great hope towards the bright future that lays before us.

Afterwards, equipped with another coffee to-go at my side, I went to a meeting with the leaders from the local center and the National Board, where we talked various things, from how empowerment should be applied practically, to what we should do if the dreaded coronavirus should affect our activity, resulting in a very productive discussion.

The evening was ended blissfully, with friends at my side and good thoughts that will echo into the near future.

Be prepared, and always remember that tomorrow might be a day when the sun steps up his game, and shines even more brightly!

Today was about scouting | Adunarea Generală Scouts Cluj 2020
Today was about scouting | Adunarea Generală Scouts Cluj 2020
Today was about scouting | Adunarea Generală Scouts Cluj 2020

The Album

Scouts Cluj | Adunarea Generală 2020
52 new photos added to shared album
Today was about scouting | Adunarea Generală Scouts Cluj 2020
]]>
<![CDATA[Întâlnirea nivelului de coordonare executivă a ONCR la Cluj | 08 - 09 februarie 2020]]>

The Album

ONCR | Întâlnire Cluj, 8 - 9 februarie
76 new photos added to shared album
]]>
https://florin.me/intalnire-nivel-executiv/62b1b2704e5c6972e4e8f581Sat, 08 Feb 2020 00:00:00 GMT

The Album

ONCR | Întâlnire Cluj, 8 - 9 februarie
76 new photos added to shared album
Întâlnirea nivelului de coordonare executivă a ONCR la Cluj | 08 - 09 februarie 2020
]]>
<![CDATA[Concert Zimbru | 12 decembrie 2019]]>

The Album

Zimbru | 12.12.19
34 new photos added to shared album
]]>
https://florin.me/concert-zimbru-12-decembrie-2019/62b1b2704e5c6972e4e8f580Thu, 12 Dec 2019 00:00:00 GMT

The Album

Zimbru | 12.12.19
34 new photos added to shared album
Concert Zimbru | 12 decembrie 2019
]]>