<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Bianca Correia</title><description>Notes from an accountant with an interest in software engineering, product and AI agents. Honest write-ups on Ruby, Rails, JavaScript, product research and learning to build software.</description><link>https://biancacorreia.com</link><language>en-GB</language><atom:link href="https://biancacorreia.com/rss.xml" rel="self" type="application/rss+xml"/><item><title>How I Researched My Way to a Mobile App Idea</title><link>https://biancacorreia.com/blog/how-i-researched-my-way-to-a-mobile-app-idea</link><guid isPermaLink="true">https://biancacorreia.com/blog/how-i-researched-my-way-to-a-mobile-app-idea</guid><description>Most people pick an app idea the way they pick a takeaway: whatever they happen to be craving that evening. I wanted to do it differently.</description><pubDate>Sun, 04 Oct 2026 04:02:21 GMT</pubDate><content:encoded>&lt;p&gt;Most people pick an app idea the way they pick a takeaway: whatever they happen to be craving that evening. I wanted to do it differently. Before writing a line of code, I decided to treat the idea itself as the most important thing to get right, and to spend real time researching before building anything.&lt;/p&gt;
&lt;p&gt;This post walks through that research in three parts. First, the process I borrowed from a founder who has done it well. Second, the two ideas that came out of my own digging, each with the diagrams and working code I used to test whether it had substance. Third, what I learned about choosing between them. The code is deliberately small. The point of writing it was to find out whether each idea could stand on its own logic, not to ship it.&lt;/p&gt;
&lt;h2&gt;Starting with someone else&apos;s journey&lt;/h2&gt;
&lt;p&gt;The spark was an article I came across on Twitter, written by a founder who built a consumer health app to a substantial annual recurring revenue figure, largely on his own with AI doing much of the building. What stayed with me was not the revenue but the order of his process. He picked the idea carefully, tested whether people cared through short videos, and only then built the product. His argument was that now AI has made building cheap, the scarce skill is choosing the right thing to build.&lt;/p&gt;
&lt;p&gt;His method for choosing was refreshingly practical. Spend time where real consumers spend theirs, on TikTok, Instagram and Reddit. Check keyword demand in the App Store with a tool such as Astro, looking for a market with some existing demand but not overwhelming competition. Then take a proven app and narrow its appeal to a smaller group of people, the way a meditation app might become a manifesting app, or a language app might become a chess teaching app. Only after that does the building start, and he says it should take a week or two rather than months. Figure 1 shows the routine I took from it.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;flowchart LR
  A([1. Observe]) --&amp;gt; B([2. Measure]) --&amp;gt; C([3. Narrow]) --&amp;gt; D([4. Validate]) --&amp;gt; E([5. Build])
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Turning the advice into a scorecard&lt;/h2&gt;
&lt;p&gt;Advice is easy to nod along to and hard to apply, so I made it concrete. For each candidate idea I rated five things from one to five: how much demand I could see, how big the gap in the market looked, how strongly I personally cared about the problem, how buildable it was for a very small team, and how clearly it could earn revenue. Demand and gap carry the most weight, because an idea nobody wants, or one that a dozen products already solve well, is dead on arrival however much I like it.&lt;/p&gt;
&lt;p&gt;The ratings below are my own rough judgements, so treat them as a thinking tool rather than a measurement. Writing the weights down was the useful part, because it forced me to say out loud what I actually valued.&lt;/p&gt;
&lt;p&gt;The two scores landed within a couple of points of each other, which told me something useful straight away: no amount of spreadsheet thinking would separate them. I would need evidence from real people. Before I get to how I plan to gather it, here are the two ideas themselves.&lt;/p&gt;
&lt;h2&gt;Idea one: a personal shopping layer that belongs to the customer&lt;/h2&gt;
&lt;p&gt;The first concept is a shopping account that belongs to the user rather than to Amazon, Google, TikTok or any single retailer. Think of it as a personal shopping brain across the entire internet. Instead of fifteen scattered wishlists on fifteen different sites, there is one intelligent home for everything you want, everything you already own, what you can afford and what you are waiting on.&lt;/p&gt;
&lt;p&gt;What excites me is the shift from search results to decisions. Imagine telling the app you have £250 for a week in Paris in October, and that you already own a black trench coat, white trainers and dark jeans. Rather than fifty jumpers under £100, it returns a small capsule of pieces that work with what you own, combine into several outfits and stay under budget, and then explains its reasoning.&lt;/p&gt;
&lt;h2&gt;The architecture in one picture&lt;/h2&gt;
&lt;p&gt;Products arrive from wherever the user finds them, whether that is a pasted link, a screenshot, a typed name or a share from TikTok. They are turned into a clean product card, then filed into one account that the user owns. The decisions the user actually pays for sit on the right, and every one of them draws on the same personal data in the middle.&lt;/p&gt;
&lt;h2&gt;Shopping DNA as a data model&lt;/h2&gt;
&lt;p&gt;The real value is not in AI recommendations, which are quickly becoming commoditised. It is in a persistent profile that I have been calling Shopping DNA. It holds a typical spending range, a ceiling for spontaneous purchases and a threshold for investment pieces. It also holds style, the brands the user loves or avoids, fabric and sizing preferences, and habits such as waiting for sales or never being shown a duplicate of something already owned. Writing it as types made me notice how much of it is simple, structured data rather than anything mysterious.&lt;/p&gt;
&lt;h2&gt;Every item has a status&lt;/h2&gt;
&lt;p&gt;A universal list becomes far stickier once every product carries a status: want, waiting for a price drop, ready to buy, purchased, repurchase or no longer interested. Those states are really a small state machine, shown in Figure 3, and writing the allowed moves down stops the app from ever doing something nonsensical, such as offering to repurchase something the user never bought.&lt;/p&gt;
&lt;h2&gt;Turning a wishlist into a verdict&lt;/h2&gt;
&lt;p&gt;Take the example of a £120 serum spotted on TikTok. The user shares it to the app, which knows the lowest tracked price was £89, that the user&apos;s budget for this kind of product is £100, and that they already own two similar serums. The answer should be a plain word, not a score: buy now, consider, wait or remove.&lt;/p&gt;
&lt;h2&gt;Spending a budget wisely&lt;/h2&gt;
&lt;p&gt;The most useful feature in the whole concept is the question it answers: what should I buy first? That is a small optimisation problem. Each item has a price and a priority, the user has a budget, and the app should pick the combination that delivers the most priority without overspending.&lt;/p&gt;
&lt;h2&gt;Starting smaller&lt;/h2&gt;
&lt;p&gt;A simpler starting point came out of this research too. It is a wishlist where you add items by link, screenshot or name, set a monthly budget, and the app tells you what to buy now, what to wait for and what to save towards. Think of it as a budgeting app for shopping decisions rather than a rival to Amazon. Beginning in a single category such as beauty keeps it focused, since beauty combines frequent purchases, impulse buying, overlapping products and discovery driven by influencers. I also like the idea of missions, where you describe a need and the app assembles it within your budget and tastes.&lt;/p&gt;
&lt;h2&gt;Idea two: a research to task workspace&lt;/h2&gt;
&lt;p&gt;The second idea is a SaaS product rather than a consumer app, and it came from a frustration I recognise in my own work. Research and task management usually live in separate tools, so you end up switching between them and cross referencing by hand. The concept is built around a task tree rather than documents or folders. A project breaks into tasks and subtasks, and every saved web page, PDF, screenshot, quote or file attaches to the exact node where it matters.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;flowchart LR
  P[&quot;Project: Launch beta&quot;] --&amp;gt; CR[&quot;Competitor research&quot;]
  P --&amp;gt; PR[&quot;Pricing&quot;]
  P --&amp;gt; ON[&quot;Onboarding&quot;]
  CR --&amp;gt; C4[&quot;Compare 4 rivals&quot;] --&amp;gt; PP[&quot;Page: pricing page&quot;] --&amp;gt; PDF[&quot;PDF: market report&quot;]
  CR --&amp;gt; IN[&quot;Interview notes&quot;] --&amp;gt; QU[&quot;Quote: user says&quot;]
  PR --&amp;gt; TP[&quot;Test price points&quot;] --&amp;gt; BM[&quot;Page: benchmark&quot;] --&amp;gt; SP[&quot;Shot: paywall&quot;]
  ON --&amp;gt; DQ[&quot;Draft questions&quot;] --&amp;gt; UX[&quot;Page: UX article&quot;]
  ON --&amp;gt; RP[&quot;Review prompt&quot;] --&amp;gt; SR[&quot;Quote: store rules&quot;]
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;The data model&lt;/h2&gt;
&lt;p&gt;A tree sounds exotic until you write it down. A single table of nodes, each pointing at its parent, covers projects, tasks and subtasks alike. Sources hang off any node, and tags sit alongside so that a topic can be pulled up across the whole tree. The tables below are everything the first version needs.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;CREATE TABLE task (
  id         BIGSERIAL PRIMARY KEY,
  project_id BIGINT NOT NULL,
  parent_id  BIGINT REFERENCES task(id) ON DELETE CASCADE,
  title      TEXT NOT NULL,
  done       BOOLEAN NOT NULL DEFAULT FALSE,
  position   INT NOT NULL DEFAULT 0
);

CREATE TABLE source (
  id         BIGSERIAL PRIMARY KEY,
  task_id    BIGINT NOT NULL REFERENCES task(id) ON DELETE CASCADE,
  kind       TEXT NOT NULL,
  url        TEXT,
  excerpt    TEXT,
  created_at TIMESTAMPTZ NOT NULL DEFAULT now()
);

CREATE TABLE tag (
  id   BIGSERIAL PRIMARY KEY,
  name TEXT UNIQUE NOT NULL
);

CREATE TABLE task_tag (
  task_id BIGINT REFERENCES task(id) ON DELETE CASCADE,
  tag_id  BIGINT REFERENCES tag(id) ON DELETE CASCADE,
  PRIMARY KEY (task_id, tag_id)
);
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Opening a task shows everything at once&lt;/h2&gt;
&lt;p&gt;The promise of the product is that you never search two tools to reconstruct why a task exists. In database terms that is one recursive query: start at a task, walk down through its subtasks, and gather every source attached along the way.&lt;/p&gt;
&lt;h2&gt;Capture at the moment of saving&lt;/h2&gt;
&lt;p&gt;The behaviour that makes the whole idea work is that the user is asked which task a clip belongs to at the moment of saving, not later. That removes the inbox that every other tool leaves you to sort. A lightweight browser extension would send the page address, title and any highlighted passage, along with the chosen task, to the server.&lt;/p&gt;
&lt;h2&gt;Where it sits in the market&lt;/h2&gt;
&lt;p&gt;What convinced me this was worth considering was the gap analysis. Tools such as ONES and Draft lean towards general team task management, while Raindrop and Fabric lean towards general knowledge capture. Nobody I found combines both around a strict task hierarchy, which leaves a narrower but underserved audience.&lt;/p&gt;
&lt;h2&gt;Choosing between them&lt;/h2&gt;
&lt;p&gt;The scorecard gave me a near tie, and that matches how it feels. The shopping idea has the larger audience and the clearer consumer habit, but it also faces giants and needs data from many retailers. The workspace has a smaller audience and a visible gap, and it comes from a problem I feel myself, which makes it much easier to talk to the right users. Neither is obviously wrong, so the next step is not more thinking. It is the founder&apos;s own test: post about each idea as content, build a tiny mock up of the killer feature, and see which one makes people ask for the link.&lt;/p&gt;
&lt;h2&gt;What the research taught me&lt;/h2&gt;
&lt;p&gt;Four lessons stand out. First, spend as much time choosing as building, because a carefully researched idea saves months of wasted effort. Second, narrow the audience, since a clear problem for a specific group is easier to explain, build and test than a general solution. Third, validate before you commit, using content and conversations with real people to see whether anyone actually wants it. Fourth, and the one that surprised me, write the core logic down as code or diagrams early. Twenty lines of planner or a single recursive query showed me which parts of each idea were solid and which were wishful thinking, and it cost an afternoon rather than a month.&lt;/p&gt;
&lt;p&gt;I am still weighing these ideas, but the process has already paid off, because I now know why I would choose one over another, not just which one I like best.&lt;/p&gt;
</content:encoded><category>product</category><category>research</category><category>sql</category><author>Bianca Correia</author></item><item><title>Building Scentfolio: A Full-Stack Fragrance Tracking Platform with Ruby on Rails</title><link>https://biancacorreia.com/blog/building-scentfolio-a-full-stack-fragrance-tracking-platform-with-ruby-on-rails</link><guid isPermaLink="true">https://biancacorreia.com/blog/building-scentfolio-a-full-stack-fragrance-tracking-platform-with-ruby-on-rails</guid><description>I chose a niche that I find exciting: fragrances. Throughout the years I have been using websites hanging on by their last html line of code to gather my…</description><pubDate>Tue, 09 Jun 2026 22:40:22 GMT</pubDate><content:encoded>&lt;h2&gt;The Problem&lt;/h2&gt;
&lt;p&gt;It was time to put all I have learnt throughout my time at Le Wagon to the test. Hearing about how to build a full stack website was sounding easier than ever. However, I wanted to put myself to the test to build something outside of the construct of Le Wagon. No challenges that I had to follow broken down by steps nor being spoon fed what the code would be to decipher whether I pass a challenge.&lt;/p&gt;
&lt;p&gt;I chose a niche that I find exciting: fragrances. Throughout the years I have been using websites hanging on by their last html line of code to gather my knowledge about fragrances. This interest came randomly but intensely. I was curious about the notes, the perfumer, and mostly excited to share my reviews on said fragrances.&lt;/p&gt;
&lt;p&gt;However, I found the websites visually unappealing and underwhelming So for my first website, I wanted to collate and put to the test if I could create a full stack website for fragrance lovers such as myself, that was actually interesting to navigate. In turn, I would ultimately end up using what I have learned to create such.&lt;/p&gt;
&lt;p&gt;Fragrance lovers often own multiple perfumes, sample new scents regularly, and develop preferences that evolve over time as your nose changes as we call it. Yet most people rely on memory, notes apps, or spreadsheets to track their fragrance journey. I wanted a better solution. That&apos;s why I built Scentfolio, a web application designed to help users track, discover, and cherish their fragrance experiences in one place.&lt;/p&gt;
&lt;h2&gt;From Idea to Application&lt;/h2&gt;
&lt;p&gt;The original vision was simple: create a digital fragrance diary web app, where users could record the scents they own and their impressions of each fragrance.&lt;/p&gt;
&lt;p&gt;As development progressed, the project evolved into a full-stack web application featuring user accounts, fragrance collections, personal scent entries and analytics dashboards.&lt;/p&gt;
&lt;h2&gt;Technology Stack - Ruby on Rails&lt;/h2&gt;
&lt;p&gt;In Le Wagon we used Ruby on Rails because it provides a robust framework for rapidly building database-driven applications. Rails allowed me to focus on solving user problems instead of spending excessive time on configuration.&lt;/p&gt;
&lt;h2&gt;Database Design&lt;/h2&gt;
&lt;p&gt;The website app stores fragrance entries and user data in a structured database, enabling users to create fragrance entries, update scent notes, tack personal ratings and maintain a fragrance history over time.&lt;/p&gt;
&lt;p&gt;Using Active Record made managing relationships and data persistence straightforward. Authentication and personalisation A fragrance journal is personal. To support this, I implemented user registration and login functionality, allowing users to securely manage their own collections and entries.&lt;/p&gt;
&lt;p&gt;The User model uses Rails&apos; built-in authentication framework.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;has_secure_password 
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Email addresses are normalized before storage:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;normalizes :email, 
with: -&amp;gt;(e) { e.strip.downcase } 
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This prevents duplicate accounts. Additional validations were used to ensure unique email addresses, minimum password length and proper email formatting.&lt;/p&gt;
&lt;p&gt;Once the user is signed in, they are able to create fragrance diary, edit existing diary entries, view the analytics and maintain a unique fragrance hsitory. I ensured that the user data and fragrance data would remain separate.&lt;/p&gt;
&lt;p&gt;The central model in the web app is the Entry model. Each entry represents a fragrance experience rather than simply a perfume bottle. This design allows users to record details such as fragrance name, brand, notes, personal rating, date worn, longevity and personal notes.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;class Entry &amp;lt; ApplicationRecord
  OCCASIONS = [ &quot;Work&quot;, &quot;Evening Out&quot;, &quot;Special Event&quot;, &quot;Casual&quot;, &quot;Date Night&quot;, &quot;Sport&quot;, &quot;Travel&quot; ].freeze

  validates :fragrance_name, presence: true,
                             length: { maximum: 100 },
                             format: { without: /&amp;lt;[^&amp;gt;]+&amp;gt;/, message: &quot;must not contain HTML&quot; }

  validates :brand, length: { maximum: 100 },
                    format: { without: /&amp;lt;[^&amp;gt;]+&amp;gt;/, message: &quot;must not contain HTML&quot; },
                    allow_blank: true

  validates :notes, length: { maximum: 1000 },
                    format: { without: /&amp;lt;[^&amp;gt;]+&amp;gt;/, message: &quot;must not contain HTML&quot; },
                    allow_blank: true

  validates :occasion, inclusion: { in: OCCASIONS, message: &quot;is not a valid occasion&quot; },
                       allow_blank: true

  validates :strength, presence: true, inclusion: { in: 1..10 }

  validates :worn_on, presence: true

  scope :recent, -&amp;gt; { order(worn_on: :desc) }
  scope :this_week, -&amp;gt; { where(worn_on: 1.week.ago..) }

  def self.favorite_occasion
    where.not(occasion: [ nil, &quot;&quot; ])
      .group(:occasion)
      .order(&quot;count_all DESC&quot;)
      .count
      .first&amp;amp;.first
  end

  def self.avg_strength
    average(:strength)&amp;amp;.round(1)
  end
end
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Treating entries as experiences rather than products creates a richer dataset and allows users to build a true fragrance journey overtime. The relationship structure is intentionally simple:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;User has_many: entries 
Entry belongs _to user
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This means the user can maintain hundreds of fragrance entries which preserving clear ownership and data integrity.&lt;/p&gt;
&lt;h2&gt;Data Validation&lt;/h2&gt;
&lt;p&gt;One of my priorities during development was ensuring that the database only stores meaningful and clean data.&lt;/p&gt;
&lt;p&gt;Rails validations are used extensively throughout the Entry model. I made sure that data validations would be necessary when inputting the fragrance name, strength rating must fall between 1 and 10, dates the fragrance was worn would be mandatory, text fields would have length restrictions and finally HTML input would be blocked to rpecent malicious content and maintain data integrity.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;validates :strength, 
presence: true, 
inclusion: { in: 1..10 }
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;To improve data consistency, fragrance occasions were restricted to a predefined list and to avoid duplicates. Rather than repeatedly writing database queries throughout the application, I used Active Record scopes to encapsulate common filters. This keeps controllers clean while making the code easier to maintain.&lt;/p&gt;
&lt;p&gt;The web app followed Rails&apos; RESTful conventions through the Entries Controller.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;class EntriesController &amp;lt; ApplicationController
  def index
    @entries = Entry.order(worn_on: :desc)
  end

  def show
  end

  def new
    @entry = Entry.new(worn_on: Date.today)
  end

  def create
    @entry = Entry.new(entry_params)
    if @entry.save
      redirect_to root_path, notice: &quot;Entry added successfully!&quot;
    else
      render :new, status: :unprocessable_entity
    end
  end

  def edit
  end

  def update
    if @entry.update(entry_params)
      redirect_to entries_path, notice: &quot;Entry updated!&quot;
    else
      render :edit, status: :unprocessable_entity
    end
  end

  def destroy
    @entry.destroy
    redirect_to entries_path, notice: &quot;Entry deleted.&quot;
  end
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;For routes, I used clean RESTful routing&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;: resources :entries 
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;which automatically generated routes for index, show, new, create, edit, update and delete. Then I added custom routes for the analytics dashboard, user registration and user login.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Rails.application.routes.draw do
  root &quot;pages#home&quot;
  get &quot;analytics&quot;, to: &quot;pages#analytics&quot;, as: :analytics
  resources :entries

  get &quot;sign-up&quot;, to: &quot;sessions#new_signup&quot;, as: :sign_up
  post &quot;sign-up&quot;, to: &quot;users#create&quot;
  get &quot;log-in&quot;, to: &quot;sessions#new_login&quot;, as: :log_in
end
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Key feature was the fragrance collection management&lt;/h2&gt;
&lt;p&gt;Users can maintain a digital inventory of their fragrances, making it easy to organise and revisit their collection. One of the most interesting aspects of the project is the analytics section. Instead of simply storing fragrance data, the application helps users understand patterns in their preferences and usage habits.&lt;/p&gt;
&lt;h2&gt;Challenges Along the Way&lt;/h2&gt;
&lt;p&gt;Building a full-stack application introduced challenges beyond front-end development. Displaying fragrance data is easy. Turning that data into useful insights for users required additional thought around dashboard design. Because the data is stored in structured tables rather than unstructured notes, these insights can be generated efficiently through database queries.&lt;/p&gt;
&lt;h2&gt;What I Learned&lt;/h2&gt;
&lt;p&gt;This project helped me strengthen my understanding of Ruby on rails architecture, MVC design patterns, database design, authentication systems and full-stack application development. Most importantly, it reinforced the value of building software around a genuine passion.&lt;/p&gt;
&lt;p&gt;Final Thoughts&lt;/p&gt;
&lt;p&gt;Scentfolio began as a simple idea and grew into a full-stack web platform that combines technology with a personal passion for fragrance.&lt;/p&gt;
&lt;p&gt;The project continues to evolve, but it has already become one of the most rewarding applications I&apos;ve built because it solves a real problem for a community I care about.&lt;/p&gt;
&lt;p&gt;Building software is always more enjoyable when it&apos;s connected to something meaningful, and for me, fragrance was the perfect place to start.&lt;/p&gt;
</content:encoded><category>rails</category><category>ruby</category><category>projects</category><author>Bianca Correia</author></item><item><title>From Static HTML to Smart Templates: A beginner&apos;s guide</title><link>https://biancacorreia.com/blog/from-static-html-to-smart-templates-a-beginner-s-guide</link><guid isPermaLink="true">https://biancacorreia.com/blog/from-static-html-to-smart-templates-a-beginner-s-guide</guid><description>When I first started learning frontend development, I thought building a webpage meant writing a lot of HTML.</description><pubDate>Wed, 18 Mar 2026 15:03:11 GMT</pubDate><content:encoded>&lt;p&gt;When I first started learning frontend development, I thought building a webpage meant writing a lot of HTML. If I wanted to show a list of movies, products, or anything repetitive, my instinct was simple: copy, paste, change the text, repeat.&lt;/p&gt;
&lt;p&gt;It worked… until it didn’t. Recently, I learned something that completely changed how I think about building web pages, most web pages are really just data and a template processed by code to produce a document (usually HTML). Once this clicked, a lot of things suddenly made sense.&lt;/p&gt;
&lt;h3&gt;The Three Ingredients of a Web Page&lt;/h3&gt;
&lt;p&gt;At a high level, many modern web pages are built using three key pieces. Data, a template and processing logic.&lt;/p&gt;
&lt;p&gt;Data can come from many places, such as a database, CSV, an API returning JSON . For example, a product API might return something like this:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;{
  &quot;product_name&quot;: &quot;Coffee Beans&quot;,
  &quot;product_description&quot;: &quot;Origin: Burundi | Roasting: Light&quot;,
  &quot;product_picture&quot;: &quot;https://example.com/coffee.jpg&quot;,
  &quot;product_price&quot;: &quot;12 EUR&quot;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;When working with APIs, one of the first things you learn is to always inspect the structure of the data. Your code needs to know the exact keys available (product_name, product_picture, etc.) so you can display them correctly.&lt;/p&gt;
&lt;h3&gt;My First Instinct: Static HTML&lt;/h3&gt;
&lt;p&gt;Let’s say we want to display a list of movies. My beginner instinct would be something like this:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;div class=&quot;card&quot;&amp;gt;
  &amp;lt;img src=&quot;movie-poster.jpg&quot;&amp;gt;
  &amp;lt;h2&amp;gt;Harry Potter and the Sorcerer&apos;s Stone&amp;lt;/h2&amp;gt;
  &amp;lt;p&amp;gt;2001&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now imagine doing that 10 times. Or 1000 times. Suddenly we run into problems if we want to redesign the card layout or change the movies, would entail updating every single card or updating each block.&lt;/p&gt;
&lt;p&gt;This approach breaks one of the first principles developers learn, to not repeat yourself (DRY). Clearly, we need a better way.&lt;/p&gt;
&lt;h3&gt;Making HTML Dynamic with JavaScript&lt;/h3&gt;
&lt;p&gt;Instead of writing every movie manually, we can fetch data from an API and generate the HTML automatically. For example, using the OMDB movie API:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;fetch(&quot;http://www.omdbapi.com/?s=harry potter&amp;amp;apikey=YOUR_KEY&quot;)
  .then(response =&amp;gt; response.json())
  .then((data) =&amp;gt; {
    console.log(data);
  });
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This gives us structured movie data like:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;{
  &quot;Title&quot;: &quot;Harry Potter and the Deathly Hallows: Part 2&quot;,
  &quot;Year&quot;: &quot;2011&quot;,
  &quot;Poster&quot;: &quot;...&quot;,
  &quot;imdbID&quot;: &quot;tt1201607&quot;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now we can dynamically generate HTML using string interpolation.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;const movieCard = `
&amp;lt;div class=&quot;card&quot;&amp;gt;
  &amp;lt;img src=&quot;${movie.Poster}&quot;&amp;gt;
  &amp;lt;h2&amp;gt;${movie.Title}&amp;lt;/h2&amp;gt;
  &amp;lt;p&amp;gt;${movie.Year}&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
`;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Then insert it into the page:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;results.insertAdjacentHTML(&quot;beforeend&quot;, movieCard);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This already solves a huge problem, now we can display hundreds of movies automatically. The layout only needs to be written once but there’s still a downside. Now our HTML lives inside JavaScript, which gets messy quickly.&lt;/p&gt;
&lt;h2&gt;A Cleaner Solution: The &lt;code&gt;&amp;lt;template&amp;gt;&lt;/code&gt; Element&lt;/h2&gt;
&lt;p&gt;One solution I learned about is the HTML &lt;code&gt;&amp;lt;template&amp;gt;&lt;/code&gt; tag. It lets you store reusable HTML inside the page without rendering it immediately.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;template id=&quot;movieCardTemplate&quot;&amp;gt;
  &amp;lt;div class=&quot;card&quot;&amp;gt;
    &amp;lt;img src=&quot;&quot;&amp;gt;
    &amp;lt;h2&amp;gt;Movie Title&amp;lt;/h2&amp;gt;
    &amp;lt;p&amp;gt;Year&amp;lt;/p&amp;gt;
  &amp;lt;/div&amp;gt;
&amp;lt;/template&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;JavaScript can then clone the template, inject the data, and render it.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;const template = document.querySelector(&quot;#movieCardTemplate&quot;);

const clone = template.content.cloneNode(true);
clone.querySelector(&quot;h2&quot;).textContent = movie.Title;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This is already a big improvement because HTML stays in HTML. JavaScript handles the logic, the two concerns are separated but if the template grows bigger, we end up writing lots of querySelectors.&lt;/p&gt;
&lt;h3&gt;Enter MustacheJS&lt;/h3&gt;
&lt;p&gt;The next thing I learned about was MustacheJS, a templating library. Instead of manually filling every field, Mustache lets you insert data directly into the template using double curly brackets.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;h2&amp;gt;{{Title}}&amp;lt;/h2&amp;gt;
&amp;lt;p&amp;gt;{{Year}}&amp;lt;/p&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;When rendered with data, it becomes:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;h2&amp;gt;Harry Potter and the Deathly Hallows: Part 2&amp;lt;/h2&amp;gt;
&amp;lt;p&amp;gt;2011&amp;lt;/p&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The magic happens with one line:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;const output = Mustache.render(template, movie);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Mustache takes: the template, the data and produces the final HTML.&lt;/p&gt;
&lt;h3&gt;Rendering Lists Automatically&lt;/h3&gt;
&lt;p&gt;One feature I found especially cool is list rendering. Instead of looping in JavaScript, the template itself can handle iteration. For example:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;{{#movies}}
  &amp;lt;h2&amp;gt;{{Title}}&amp;lt;/h2&amp;gt;
  &amp;lt;p&amp;gt;{{Year}}&amp;lt;/p&amp;gt;
{{/movies}}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Mustache will repeat that block for every movie in the list. Which means our JavaScript becomes incredibly simple:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;const output = Mustache.render(template, { 
  movies: data.Search }
);
results.innerHTML = output;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Cleaner code, less logic, easier maintenance.&lt;/p&gt;
&lt;h3&gt;And Then There Are Frameworks&lt;/h3&gt;
&lt;p&gt;At their core, frameworks are just an evolution of the same idea, to take data, bind it to a template which keeps everything is sync automatically.&lt;/p&gt;
&lt;p&gt;Frameworks also introduce components, which are like reusable mini-templates with their own logic. For example, instead of writing a movie card 100 times, you define it once:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;MovieCard :title=&quot;movie.title&quot; :year=&quot;movie.year&quot; /&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Each has its own template, receives data and can be reused anywhere. This is basically templating, but scaled up in a really clean way. Frameworks combine a lot of things we&apos;ve seen, such as templating, data binding and events handling. So instead of stitching together multiple tools, you get a structured way to build interactive apps.&lt;/p&gt;
&lt;h3&gt;Why This Feels Like a Turning Point&lt;/h3&gt;
&lt;p&gt;For me, this is where frontend development started to feel less like “editing HTML” and more like building systems. You’re no longer just rendering static pages, you&apos;re creating interfaces that update in real time, respond to user actions and stay in sync with data.&lt;/p&gt;
&lt;h3&gt;Final Thought (From a Beginner)&lt;/h3&gt;
&lt;p&gt;One thing I’m learning as a beginner is that there’s rarely a single “best” solution. Sometimes, static HTMP is perfectly fine. Sometimes, JavaScript interpolation is enough. Other times, you need templating libraries or a full framework. The key is understanding the trade-offs and choosing the right tool for the problem. And honestly, that’s one of the most exciting parts of learning to build software. You start seeing how the pieces fit together.&lt;/p&gt;
</content:encoded><category>javascript</category><category>html</category><category>frontend</category><author>Bianca Correia</author></item><item><title>Learning Stimulus JS as a New Developer: My First Impressions</title><link>https://biancacorreia.com/blog/learning-stimulus-js-as-a-new-developer-my-first-impressions</link><guid isPermaLink="true">https://biancacorreia.com/blog/learning-stimulus-js-as-a-new-developer-my-first-impressions</guid><description>When you&apos;re learning web development, JavaScript frameworks can feel… intimidating. At least they did for me.</description><pubDate>Thu, 12 Mar 2026 14:12:03 GMT</pubDate><content:encoded>&lt;p&gt;When you&apos;re learning web development, JavaScript frameworks can feel… intimidating. At least they did for me.&lt;/p&gt;
&lt;p&gt;When I first started exploring frontend tools, I kept hearing about frameworks that required entire application architectures, build tools, component systems, and a bunch of concepts that felt overwhelming as a new developer.&lt;/p&gt;
&lt;p&gt;Then I came across Stimulus, and it honestly felt like a breath of fresh air. Instead of replacing your html.erb, Stimulus does something much simpler. It adds Javascript behavior to the html.erb you already have.&lt;/p&gt;
&lt;p&gt;As someone still learning the ropes, this approach made things click much faster. So here’s a quick walkthrough of what I’ve been learning about Stimulus and why I think it’s such a great tool for beginner developers.&lt;/p&gt;
&lt;h3&gt;The Problem I Kept Running Into&lt;/h3&gt;
&lt;p&gt;While learning backend development with Ruby on Rails, I noticed something. Rails is great at generating pages and handling server logic, but sometimes you just want small interactive features. My first instinct was to reach for plain JavaScript and start using things like :&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;document.querySelector()
 addEventListener()
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Which works… but quickly becomes messy when your page grows. That’s where Stimulus comes in.&lt;/p&gt;
&lt;h3&gt;What Stimulus Actually Is&lt;/h3&gt;
&lt;p&gt;Stimulus is a lightweight JavaScript framework created by the team behind Basecamp. Instead of controlling your entire UI, it focuses on injecting behavior onto your html.erb. Stimulus works by connecting JavaScript to html.erb using data attributes.&lt;/p&gt;
&lt;p&gt;At first this looked strange to me, but once I understood it, it actually felt really clean.&lt;/p&gt;
&lt;h3&gt;The Core Idea: Controllers&lt;/h3&gt;
&lt;p&gt;In Stimulus, JavaScript behavior lives inside something called a controller. A controller is just a JavaScript class.&lt;/p&gt;
&lt;p&gt;When the page loads, Stimulus automatically connects this controller to any html.erb element that declares it, for example:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;div data-controller=&quot;example&quot;&amp;gt;&amp;lt;/div&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;That &lt;code&gt;data-controller&lt;/code&gt; attribute is what links your HTML to your JavaScript. Once I understood that connection, everything else started making more sense.&lt;/p&gt;
&lt;h3&gt;Actions: Listening for Events&lt;/h3&gt;
&lt;p&gt;Stimulus also gives you a really clean way to handle events. Instead of writing JavaScript like this:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;button.addEventListener(&quot;click&quot;, ...)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You define the event directly in your html.erb. For example:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;button data-action=&quot;click-&amp;gt;disable-button#disable&quot;&amp;gt; 
Click me 
&amp;lt;/button&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This code is saying that we are listening for a click, using a disable-button controller and running the disable method.&lt;/p&gt;
&lt;p&gt;When I first saw this syntax it looked weird, but after using it a few times it actually makes your html.erb very self-explanatory.&lt;/p&gt;
&lt;h3&gt;Targets: Accessing Elements Easily&lt;/h3&gt;
&lt;p&gt;One thing I struggled with early in JavaScript was selecting elements correctly. Stimulus solves this with targets. For example:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;div data-controller=&quot;disable-button&quot;&amp;gt;
 &amp;lt;button data-disable-button-target=&quot;button&quot;&amp;gt; 
    Click me 
&amp;lt;/button&amp;gt; 

 &amp;lt;a data-disable-button-target=&quot;link&quot; class=&quot;d-none&quot;&amp;gt; 
   Reset
 &amp;lt;/a&amp;gt; 
&amp;lt;/div&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Then inside the controller you simply declare:&lt;/p&gt;
&lt;p&gt;static targets = [&quot;button&quot;, &quot;link&quot;]&lt;/p&gt;
&lt;p&gt;Now Stimulus automatically gives you: this.buttonTarget ; this.linkTarget. No querySelector needed. As someone still getting comfortable with DOM manipulation, this felt like a really nice abstraction.&lt;/p&gt;
&lt;h3&gt;My First Stimulus Feature&lt;/h3&gt;
&lt;p&gt;One of the first things I built was a button that disables itself and reveals a reset link.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;import { Controller } from &quot;@hotwired/stimulus&quot;

export default class extends Controller { 
  static targets = [&quot;button&quot;, &quot;link&quot;] 

  disable() { 
    this.buttonTarget.innerText = &quot;Bingo!&quot; 
    this.buttonTarget.setAttribute(&quot;disabled&quot;, &quot;&quot;)
    this.linkTarget.classList.remove(&quot;d-none&quot;)
  }

  reset() {
    this.buttonTarget.innerText = &quot;Click me!&quot;
    this.buttonTarget.removeAttribute(&quot;disabled&quot;)
    this.linkTarget.classList.add(&quot;d-none&quot;)
  }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Stimulus + APIs&lt;/h3&gt;
&lt;p&gt;Another thing I tried was using Stimulus with an API to search for movies. The controller fetches data and inserts results into the page.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;fetch(`http://www.omdbapi.com/?s=${query}&amp;amp;apikey=YOUR_KEY`)
  .then(response =&amp;gt; response.json())
  .then(data =&amp;gt; { 
    data.Search.forEach(movie =&amp;gt; { 
      const movieTag = `
        &amp;lt;li&amp;gt; 
           &amp;lt;img src=&quot;\({movie.Poster}&quot; alt=&quot;\){movie.Title}&quot;&amp;gt;
        &amp;lt;/li&amp;gt; `
      this.resultsTarget.insertAdjacentHTML(&quot;beforeend&quot;, movieTag)
    })
})
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Seeing real data appear dynamically on the page was one of those “okay this is cool” moments.&lt;/p&gt;
&lt;h3&gt;Why I Think Stimulus Is Great for Beginners&lt;/h3&gt;
&lt;p&gt;As a new developer, I think Stimulus is great because it:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;builds on basic HTML and JavaScript concepts&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;avoids overwhelming frameworks&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;keeps JavaScript organised&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Instead of forcing you to learn an entire frontend ecosystem, it helps you improve your existing JavaScript skills.&lt;/p&gt;
&lt;h3&gt;Final Thoughts&lt;/h3&gt;
&lt;p&gt;Learning web development sometimes feels like trying to drink from a firehose. There are so many frameworks, tools, and patterns that it’s easy to feel behind. What I like about Stimulus is that it doesn’t try to reinvent everything. It simply helps you write cleaner, more structured JavaScript on top of the HTML you already understand. And as someone still early in their software engineering journey, that approach makes learning feel a lot more manageable.&lt;/p&gt;
</content:encoded><category>javascript</category><category>rails</category><category>stimulus</category><author>Bianca Correia</author></item><item><title>HTTP &amp; API&apos;s</title><link>https://biancacorreia.com/blog/http-api-s</link><guid isPermaLink="true">https://biancacorreia.com/blog/http-api-s</guid><description>If you’ve ever clicked something on a webpage that looks clickable… but absolutely nothing happens, you know that weird moment of confusion.</description><pubDate>Mon, 09 Mar 2026 22:03:53 GMT</pubDate><content:encoded>&lt;h2&gt;Making Things Clickable&lt;/h2&gt;
&lt;p&gt;If you’ve ever clicked something on a webpage that &lt;em&gt;looks&lt;/em&gt; clickable… but absolutely nothing happens, you know that weird moment of confusion.&lt;/p&gt;
&lt;p&gt;You hover. The cursor changes.&lt;br /&gt;
You click again.&lt;br /&gt;
Still nothing.&lt;/p&gt;
&lt;p&gt;That was me recently while working through some front-end exercises. And weirdly enough, that tiny frustration ended up teaching me a lot about how the browser actually works.&lt;/p&gt;
&lt;p&gt;I’m currently learning software engineering and documenting what I build along the way. Two exercises recently helped a bunch of things “click” (literally and figuratively):&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;building a multi-select sports picker using DOM events&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;building a geocoding tool that talks to a real external API&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Both sound small, but they forced me to understand two really important pieces of web development, how to make a page respond to user actions and how to fetch real data from the internet and use it inside your app&lt;/p&gt;
&lt;p&gt;Picture this: a grid of 6 sports cards. They look clickable. When you hover, the cursor changes. But when you click... nothing. Crickets. The fix sounds simple, but it taught me something fundamental about how the browser works.&lt;/p&gt;
&lt;p&gt;Before writing a single line of JavaScript, I learned to ask: &lt;em&gt;what actually needs to happen?&lt;/em&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;const sports = document.querySelectorAll(&apos;.sport&apos;);
 sports.forEach((sport) =&amp;gt; { 
 sport.addEventListener(&apos;click&apos;, (event) =&amp;gt; {                                    
  event.currentTarget.classList.toggle(&apos;active&apos;
   ); 
 }); 
});
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;querySelectorAll grabs all matching elements as a NodeList&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;forEach loops over each one&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;addEventListener(&apos;click&apos;, ...) attaches a listener that fires on click&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;event.currentTarget the specific element that was clicked&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;classList.toggle(&apos;active&apos;) adds the class if absent, removes it if present&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The CSS already had &lt;code&gt;.active&lt;/code&gt; styles defined. My job was just to wire up the toggle.&lt;/p&gt;
&lt;p&gt;One thing that surprised me early on: &lt;strong&gt;in JavaScript, functions are values&lt;/strong&gt;. You can store them in variables and pass them around without calling them. This is huge for cleaning up nested code. The original code had 3 levels of indentation, not ideal. Here&apos;s the refactored version:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;const toggleActiveClass = (event) =&amp;gt; { event.currentTarget.classList.toggle(&apos;active&apos;); };

const bindSportToClick = (sport) =&amp;gt; { sport.addEventListener(&apos;click&apos;, toggleActiveClass); };

const sports = document.querySelectorAll(&apos;.sport&apos;); sports.forEach(bindSportToClick);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Notice: forEach(bindSportToClick) ,no parentheses after bindSportToClick. We&apos;re passing the function itself as a callback, not calling it. This tripped me up the first time, but once it clicked , it felt like a superpower.&lt;/p&gt;
&lt;h2&gt;Talking to the Internet&lt;/h2&gt;
&lt;p&gt;An API (Application Programming Interface) is basically a door into someone else&apos;s server. You send a request in a specific format, they send data back. In web development, this usually means HTTP requests , the same protocol your browser uses to load every web page you&apos;ve ever visited. The most common type for fetching data is a GET request. You&apos;re not sending anything new to the server, you&apos;re asking it to give you something.&lt;/p&gt;
&lt;p&gt;In one of the challenges, I had to build a form where a user types an address, hits submit, and sees the GPS coordinates returned , using the Mapbox Geocoding API.&lt;/p&gt;
&lt;p&gt;After signing up for a free Mapbox account and getting an API key, the documentation told me I can call:&lt;/p&gt;
&lt;p&gt;&quot;&lt;a href=&quot;https://api.mapbox.com/search/geocode/v6/forward?q=Los%20Angeles&amp;amp;access_token=YOUR-API-KEY&quot;&gt;https://api.mapbox.com/search/geocode/v6/forward?q=Los%20Angeles&amp;amp;access_token=YOUR-API-KEY&lt;/a&gt;&quot;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;const form = document.querySelector(&apos;form&apos;);

form.addEventListener(&apos;submit&apos;, (event) =&amp;gt; { event.preventDefault();
  event.preventDefault();

const address = event.currentTarget.querySelector(&apos;input[type=&quot;text&quot;]&apos;).value; fetchCoordinates(address); 
});
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Event.preventDefault() was a revelation. Without it, submitting a form causes a full page reload and wipes all your JavaScript state. To fetch the data, I wrote:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;const fetchCoordinates = (address) =&amp;gt; { 
 const apiKey = &apos;YOUR-API-KEY&apos;; 
 const url = `https://api.mapbox.com/search/geocode/v6/forward?            q=\({address}&amp;amp;access_token=\){apiKey}`; 
 fetch(url) 
  .then(response =&amp;gt; response.json()) 
  .then(data =&amp;gt; { 
    console.log(data); 

    const coordinates = data.features[0].geometry.coordinates; 
    const longitude = coordinates[0]; 
    const latitude = coordinates[1];

    document.querySelector(&apos;#coordinates&apos;)
     .innerText = `Latitude: \({latitude}, Longitude: \){longitude}`; 
  }); 
};
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;A few things worth noting:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;fetch() returns a promise, asynchronous code that resolves when the server responds&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;.then(response =&amp;gt; response.json () ), parses the raw HTTP response into a JavaScript object&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The data is deeply nested, data.features[0].gemetry.coordinates, always console.long(data) first and explore the shape of the response&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Mapbox returns longitude first, latitude second&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Going from &quot;user types an address&quot; to &quot;here&apos;s a live map with a pin on it&quot; using around 20 lines of code felt genuinely magical the first time it worked. The browser is an event-driven machine. Once that clicked for me, everything started making more sense.&lt;/p&gt;
&lt;h3&gt;Last Thoughts&lt;/h3&gt;
&lt;p&gt;Write pseudo-code first. It forces you to think before you type. Functions are values in JavaScript. Pass them around without calling them for cleaner callbacks. Always console log API responses first . I got to see how web pages go from static HTML… to something that actually reacts to users and pulls live data from external services.&lt;/p&gt;
</content:encoded><category>javascript</category><category>apis</category><category>frontend</category><author>Bianca Correia</author></item><item><title>JavaScript &amp; the DOM</title><link>https://biancacorreia.com/blog/javascript-and-the-dom</link><guid isPermaLink="true">https://biancacorreia.com/blog/javascript-and-the-dom</guid><description>When I first started learning JavaScript, most of what I wrote lived in the console.</description><pubDate>Tue, 17 Feb 2026 09:00:23 GMT</pubDate><content:encoded>&lt;p&gt;When I first started learning JavaScript, most of what I wrote lived in the console.&lt;/p&gt;
&lt;p&gt;Variables changed.&lt;br /&gt;
Functions ran.&lt;br /&gt;
Numbers updated.&lt;/p&gt;
&lt;p&gt;But the page itself?&lt;br /&gt;
It just… sat there. Frozen in time.&lt;/p&gt;
&lt;p&gt;Then I started working with the DOM, and suddenly JavaScript stopped being just logic and started becoming interaction. Buttons responded. Lists grew. Content appeared out of nowhere. The page felt alive.&lt;/p&gt;
&lt;p&gt;This article is about how a set of DOM challenges taught me what JavaScript is really for, changing what the user sees, without refreshing the page.&lt;/p&gt;
&lt;h2&gt;The DOM Is Not Your HTML File&lt;/h2&gt;
&lt;p&gt;One of the biggest mindset shifts was understanding what the DOM actually is. The Document Object Model is the browser’s internal representation of your HTML. It’s not the file you wrote — it’s the &lt;em&gt;tree&lt;/em&gt; the browser builds from it. Which means your page is no longer static.&lt;/p&gt;
&lt;h2&gt;DOM Manipulation with Selectors&lt;/h2&gt;
&lt;p&gt;One of the challenges focused on using CSS selectors inside JavaScript to manipulate the page. The instructions were simple, to use our knowledge of CSS selectors to dynamically manipulate the page using JavaScript.&lt;/p&gt;
&lt;p&gt;Learning JavaScript with the DOM helped me understand that web pages are not fixed once they load. Instead of JavaScript just changing numbers or running logic in the background, it can change what the user actually sees on the screen. The browser turns HTML into a structure called the DOM, and JavaScript can move through it, change it, remove parts of it, or add new content at any time.&lt;/p&gt;
&lt;p&gt;The setup felt very “developer real-life”:&lt;/p&gt;
&lt;p&gt;Run a local server:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;serve
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Open &lt;a href=&quot;http://localhost:8000/&quot;&gt;&lt;code&gt;localhost:8000&lt;/code&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Edit &lt;code&gt;lib/dom.js&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Refresh the browser&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Watch tests turn green one by one&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;So instead of editing markup directly, I was doing things like selecting elements with &lt;code&gt;querySelector&lt;/code&gt;,&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;const title = document.querySelector(&quot;h1&quot;); 
const items = document.querySelectorAll(&quot;li&quot;);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Once elements were selected, I could change their content:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;title.innerText = &quot;DOM Manipulation in Action&quot;;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Traversing parents and children, I also learned how to add new elements to the page by creating nodes and inserting them into the DOM:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;const newItem = document.createElement(&quot;li&quot;); 
newItem.innerText = &quot;New list item&quot;; 
document.querySelector(&quot;ul&quot;).appendChild(newItem);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Removing elements was just as important, and showed how flexible the DOM really is:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;const itemToRemove = document.querySelector(&quot;.old-item&quot;);
itemToRemove.remove();
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Every refresh was feedback.&lt;/p&gt;
&lt;p&gt;By practicing with challenges that involved selecting elements and updating them, I could see my code immediately affect the page. Building a fake email inbox made this even clearer, because new messages could appear without refreshing the page, just like in real apps such as Gmail. These exercises showed me that interactive websites work by using JavaScript to update the DOM again and again over time, turning simple code into real user experiences.&lt;/p&gt;
</content:encoded><category>javascript</category><category>dom</category><category>frontend</category><author>Bianca Correia</author></item><item><title>Building a Responsive Signup Form with Bootstrap (Without Losing Your Mind)</title><link>https://biancacorreia.com/blog/building-a-responsive-signup-form-with-bootstrap-without-losing-your-mind</link><guid isPermaLink="true">https://biancacorreia.com/blog/building-a-responsive-signup-form-with-bootstrap-without-losing-your-mind</guid><description>Forms are everywhere. Login forms, signup forms, checkout forms, newsletter forms… and yet, they’re one of the easiest things to mess up.</description><pubDate>Thu, 12 Feb 2026 20:59:40 GMT</pubDate><content:encoded>&lt;p&gt;Forms are everywhere. Login forms, signup forms, checkout forms, newsletter forms… and yet, they’re one of the easiest things to mess up. Too wide on desktop, too cramped on mobile, ugly labels, confusing layout — we’ve all suffered through bad forms.&lt;/p&gt;
&lt;p&gt;So today, I built a responsive signup form using Bootstrap, and along the way I learned how powerful (and friendly) Bootstrap’s grid system really is.&lt;/p&gt;
&lt;p&gt;Let’s break it down.&lt;/p&gt;
&lt;h2&gt;Objective&lt;/h2&gt;
&lt;p&gt;The goal was simple:&lt;br /&gt;
Build a responsive signup form that looks good on all screen sizes. That means full width on mobile, centered and nicely sized on tablets and laptops, easy to read , easy to use and accessible. Sounds basic… but the trick is &lt;em&gt;how&lt;/em&gt; you place the form on the page.&lt;/p&gt;
&lt;h2&gt;The Grid Offset Technique&lt;/h2&gt;
&lt;p&gt;Bootstrap’s grid system is built on flexbox. That means we can use alignment utilities to position our form exactly where we want it.&lt;/p&gt;
&lt;p&gt;Here’s the layout:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;div class=&quot;container&quot;&amp;gt;

&amp;lt;div class=&quot;row justify-content-center&quot;&amp;gt;

&amp;lt;div class=&quot;col-12 col-sm-4&quot;&amp;gt;

&amp;lt;form action=&quot;&quot;&amp;gt; &amp;lt;!-- Your form content --&amp;gt; &amp;lt;/form&amp;gt;

&amp;lt;/div&amp;gt;

&amp;lt;/div&amp;gt;

&amp;lt;/div&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;What’s happening here?&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;.row&lt;/code&gt; is a flexbox&lt;/p&gt;
&lt;p&gt;&lt;code&gt;justify-content-center&lt;/code&gt; centers the form horizontally&lt;/p&gt;
&lt;p&gt;&lt;code&gt;col-12&lt;/code&gt; → full width on mobile&lt;/p&gt;
&lt;p&gt;&lt;code&gt;col-sm-4&lt;/code&gt; → takes 33% of the screen on tablets and larger&lt;/p&gt;
&lt;p&gt;Bootstrap lets you scale your layout without writing complicated CSS.&lt;/p&gt;
&lt;h2&gt;Understanding HTML Forms&lt;/h2&gt;
&lt;p&gt;At its core, a form is just a collection of inputs:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;form action=&quot;#&quot;&amp;gt;
&amp;lt;label for=&quot;your-email&quot;&amp;gt;Your email&amp;lt;/label&amp;gt;

&amp;lt;input type=&quot;email&quot; id=&quot;your-email&quot; placeholder=&quot;ana@gmail.com&quot;&amp;gt;

&amp;lt;input type=&quot;submit&quot; value=&quot;Sign In&quot;&amp;gt;

&amp;lt;/form&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Because when labels are linked properly, users can click the label and jump straight into the input, which is good accessibility.&lt;/p&gt;
&lt;h2&gt;Dropdown Lists&lt;/h2&gt;
&lt;p&gt;Dropdowns use &lt;code&gt;&amp;lt;select&amp;gt;&lt;/code&gt; and &lt;code&gt;&amp;lt;option&amp;gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;They work just like inputs — they just give the user predefined choices.&lt;/p&gt;
&lt;h2&gt;Styling with Bootstrap Form Classes&lt;/h2&gt;
&lt;p&gt;Bootstrap gives us ready-made form styles:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;.form-control&lt;/code&gt; -&amp;gt; styles inputs and selects&lt;/p&gt;
&lt;p&gt;&lt;code&gt;.form-label&lt;/code&gt; -&amp;gt; styles labels&lt;/p&gt;
&lt;p&gt;&lt;code&gt;.mb-3&lt;/code&gt; -&amp;gt; adds spacing between fields&lt;/p&gt;
&lt;p&gt;&lt;code&gt;.form-text&lt;/code&gt; -&amp;gt; small hint text&lt;/p&gt;
&lt;p&gt;&lt;code&gt;.btn&lt;/code&gt; &amp;amp; &lt;code&gt;.btn-primary&lt;/code&gt; -&amp;gt; button styling&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;form action=&quot;#&quot;&amp;gt;
&amp;lt;div class=&quot;mb-3&quot;&amp;gt;

&amp;lt;label for=&quot;email&quot; class=&quot;form-label&quot;&amp;gt;Your email&amp;lt;/label&amp;gt;

&amp;lt;input type=&quot;email&quot; id=&quot;email&quot; class=&quot;form-control&quot;&amp;gt;

&amp;lt;/div&amp;gt;

&amp;lt;div class=&quot;mb-3&quot;&amp;gt;

&amp;lt;label for=&quot;password&quot; class=&quot;form-label&quot;&amp;gt;Your password&amp;lt;/label&amp;gt;

&amp;lt;input type=&quot;password&quot; id=&quot;password&quot; class=&quot;form-control&quot;&amp;gt;

&amp;lt;div id=&quot;password&quot; class=&quot;form-text&quot;&amp;gt;Your password must be at least 6 characters long and contain letters and numbers.&amp;lt;/div&amp;gt;

&amp;lt;/div&amp;gt;

&amp;lt;input type=&quot;submit&quot; value=&quot;Sign In&quot; class=&quot;btn btn-primary&quot;&amp;gt;

&amp;lt;/form&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This already looked professional with almost no CSS.&lt;/p&gt;
&lt;h2&gt;Accessibility: Hidden but Not Forgotten&lt;/h2&gt;
&lt;p&gt;Sometimes you want minimalist design with no visible labels. Bootstrap lets you hide labels visually but keep them readable by screen readers:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;form action=&quot;#&quot;&amp;gt;
&amp;lt;div class=&quot;mb-3&quot;&amp;gt;

&amp;lt;label for=&quot;email-simple&quot; class=&quot;visually-hidden&quot;&amp;gt;Email&amp;lt;/label&amp;gt; &amp;lt;input type=&quot;email&quot; id=&quot;email-simple&quot; class=&quot;form-control&quot; placeholder=&quot;Email&quot;&amp;gt;

&amp;lt;/div&amp;gt;

&amp;lt;div class=&quot;mb-3&quot;&amp;gt;

&amp;lt;label for=&quot;password-simple&quot; class=&quot;visually-hidden&quot;&amp;gt;Password&amp;lt;/label&amp;gt; &amp;lt;input type=&quot;password&quot; id=&quot;password-simple&quot; class=&quot;form-control&quot; placeholder=&quot;Password&quot;&amp;gt;

&amp;lt;/div&amp;gt; &amp;lt;input type=&quot;submit&quot; value=&quot;Sign In&quot; class=&quot;btn btn-primary&quot;&amp;gt; &amp;lt;/form&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This keeps your form clean, accessible and user-friendly. Never remove labels completely — just hide them properly.&lt;/p&gt;
&lt;h2&gt;Inline Forms (Side by Side Layout)&lt;/h2&gt;
&lt;p&gt;Want your inputs to appear on one line on desktop but stack on mobile? Bootstrap’s grid handles that too:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;form action=&quot;#&quot; class=&quot;row row-cols-lg-auto&quot;&amp;gt;
&amp;lt;div class=&quot;col-12&quot;&amp;gt;

&amp;lt;label for=&quot;email-inline&quot; class=&quot;visually-hidden&quot;&amp;gt;Email&amp;lt;/label&amp;gt;

&amp;lt;input type=&quot;email&quot; id=&quot;email-inline&quot; class=&quot;form-control&quot; placeholder=&quot;Email&quot;&amp;gt;

&amp;lt;/div&amp;gt;

&amp;lt;div class=&quot;col-12&quot;&amp;gt;

&amp;lt;label for=&quot;password-inline&quot; class=&quot;visually-hidden&quot;&amp;gt;Password&amp;lt;/label&amp;gt;

&amp;lt;input type=&quot;password&quot; id=&quot;password-inline&quot; class=&quot;form-control&quot; placeholder=&quot;Password&quot;&amp;gt;

&amp;lt;/div&amp;gt;

&amp;lt;div class=&quot;col-12&quot;&amp;gt;

&amp;lt;input type=&quot;submit&quot; value=&quot;Sign In&quot; class=&quot;btn btn-primary&quot;&amp;gt;

&amp;lt;/div&amp;gt;

&amp;lt;/form&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;On mobile: stacked. On large screens: inline. Zero media queries needed.&lt;/p&gt;
&lt;h2&gt;Final Thoughts&lt;/h2&gt;
&lt;p&gt;Bootstrap turns form-building from a painful chore into a design puzzle you can actually enjoy. With just a few classes, you get:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;responsiveness&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;accessibility&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;clean layout&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;professional look&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Forms might be “just inputs”, but when done right, they feel smooth, intuitive, and modern — and that’s exactly what users expect today.&lt;/p&gt;
&lt;hr /&gt;
&lt;hr /&gt;
</content:encoded><category>css</category><category>bootstrap</category><category>frontend</category><author>Bianca Correia</author></item><item><title>Learning HTML &amp; CSS Selectors by Building A Profile Page</title><link>https://biancacorreia.com/blog/learning-html-and-css-selectors-by-building-a-profile-page</link><guid isPermaLink="true">https://biancacorreia.com/blog/learning-html-and-css-selectors-by-building-a-profile-page</guid><description>When I started learning HTML and CSS, I quickly realised that writing content is only half the story.</description><pubDate>Tue, 10 Feb 2026 21:24:24 GMT</pubDate><content:encoded>&lt;p&gt;When I started learning HTML and CSS, I quickly realised that writing content is only half the story. The real magic happens when you learn how to &lt;strong&gt;select&lt;/strong&gt; elements and style them properly. To practise this, I built a simple profile page using semantic HTML and CSS selectors, while running everything on a local server.&lt;/p&gt;
&lt;p&gt;This project helped me understand how structure (HTML) and design (CSS) work together.&lt;/p&gt;
&lt;h2&gt;Project Setup&lt;/h2&gt;
&lt;p&gt;Before writing any code, I had to organise my project properly. Inside my profile folder, I created a directory for images:&lt;/p&gt;
&lt;p&gt;cd profile&lt;/p&gt;
&lt;p&gt;mkdir images&lt;/p&gt;
&lt;p&gt;code.&lt;/p&gt;
&lt;p&gt;This keeps my project clean and makes it easier to manage assets like profile pictures and icons.&lt;/p&gt;
&lt;h2&gt;Running a Local Server&lt;/h2&gt;
&lt;p&gt;To preview my page in the browser, I used a local web server: serve&lt;/p&gt;
&lt;p&gt;This command was already set up as an alias. Once it was running, I could visit my project at: &lt;a href=&quot;http://localhost:8000/&quot;&gt;http://localhost:8000&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This showed my HTML page exactly as a real website would appear.&lt;/p&gt;
&lt;h2&gt;Dealing with Browser Cache&lt;/h2&gt;
&lt;p&gt;Modern browsers cache files to load them faster. This includes:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;HTML files&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;CSS stylesheets&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Images&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Sometimes this means my changes didn’t appear straight away. To fix this, I used:&lt;/p&gt;
&lt;h2&gt;Cmd + Shift + R&lt;/h2&gt;
&lt;p&gt;This forces a hard refresh and clears the cache so the newest version of my code is loaded.&lt;/p&gt;
&lt;h2&gt;Building the HTML Structure&lt;/h2&gt;
&lt;p&gt;The goal was to build a simple profile page containing:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;An image of myself&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;A header and sub-header with my name and job title&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;A short description&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;A button&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;A list of social links&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I used proper semantic HTML tags instead of generic &lt;code&gt;&amp;lt;div&amp;gt;&lt;/code&gt; elements:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;&amp;lt;header&amp;gt;&lt;/code&gt; for the top section&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;&amp;lt;main&amp;gt;&lt;/code&gt; for the main content&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;&amp;lt;section&amp;gt;&lt;/code&gt; for grouped content&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I also added useful metadata inside the &lt;code&gt;&amp;lt;head&amp;gt;&lt;/code&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;meta charset=”utf-8”&amp;gt;
&amp;lt;title&amp;gt; My Profile &amp;lt;/title&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This makes sure the browser understands the character encoding and displays the correct page title.&lt;/p&gt;
&lt;h2&gt;Accessibility Matters&lt;/h2&gt;
&lt;p&gt;One important thing I learned was how to write accessible HTML. For example, images should always include descriptive &lt;code&gt;alt&lt;/code&gt; text for accessibility.&lt;/p&gt;
&lt;p&gt;Instead of describing the purpose (“profile photo”), the &lt;code&gt;alt&lt;/code&gt; text explains what is actually visible in the image. This helps screen readers and improves accessibility scores.&lt;/p&gt;
&lt;h2&gt;Styling with CSS Selectors&lt;/h2&gt;
&lt;p&gt;CSS selectors are how we tell the browser &lt;em&gt;which&lt;/em&gt; HTML elements to style. This project helped me understand several important types of selectors:&lt;/p&gt;
&lt;h3&gt;1. Element selectors&lt;/h3&gt;
&lt;p&gt;These target all elements of a certain type such as body and h1.&lt;/p&gt;
&lt;h3&gt;2. Class selectors&lt;/h3&gt;
&lt;p&gt;These target elements with a specific class, such as .profile.card&lt;/p&gt;
&lt;h3&gt;3. Descendant selectors&lt;/h3&gt;
&lt;p&gt;These target elements inside other elements such as header h1&lt;/p&gt;
&lt;p&gt;This only styles &lt;code&gt;&amp;lt;h1&amp;gt;&lt;/code&gt; elements that are inside a &lt;code&gt;&amp;lt;header&amp;gt;&lt;/code&gt;.&lt;/p&gt;
&lt;h3&gt;4. Attribute selectors&lt;/h3&gt;
&lt;p&gt;Useful for links and buttons such as a[target=”_blank”], this only styles links that open in a new tab.&lt;/p&gt;
&lt;h2&gt;Adding Icons with Font Awesome&lt;/h2&gt;
&lt;p&gt;To make the social links look nicer, I used Font Awesome icons by adding this to my &lt;code&gt;&amp;lt;head&amp;gt;&lt;/code&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;link rel=&quot;stylesheet&quot; href=&quot;filepath&quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This allowed me to write:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;i class=&quot;fab fa-twitter&quot;&amp;gt;Twitter&amp;lt;/i&amp;gt; 
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Because icons are fonts, I could style them easily using CSS (change size, color, or add hover effects).&lt;/p&gt;
&lt;h2&gt;The Importance of Indentation&lt;/h2&gt;
&lt;p&gt;One of the most valuable habits I learned is proper indentation. HTML has a lot of nested elements, and messy indentation makes code hard to read and debug. Clean indentation makes the structure obvious and prevents mistakes.&lt;/p&gt;
&lt;h2&gt;Finishing and Saving My Work&lt;/h2&gt;
&lt;p&gt;Once my profile page was complete, I pushed it to GitHub. Then I copied it into the next exercise folder:This let me reuse my work and build on top of it instead of starting from scratch.&lt;/p&gt;
&lt;h2&gt;Adding Fonts and Colors with CSS&lt;/h2&gt;
&lt;p&gt;After building the structure of my profile page with HTML, the next step was to bring it to life using CSS. This stage focused on choosing fonts and colors that make the page readable, visually balanced, and more personal.&lt;/p&gt;
&lt;p&gt;To begin, I copied my existing profile into the new challenge folder and created a CSS file, I then linked this &lt;code&gt;style.css&lt;/code&gt; file to my HTML document so the browser could apply my styles.&lt;/p&gt;
&lt;h2&gt;Styling the Body&lt;/h2&gt;
&lt;p&gt;I started by styling the &lt;code&gt;&amp;lt;body&amp;gt;&lt;/code&gt; element. Since most text is inside the body, these rules affect paragraphs, list items, and general content.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;body {
background-color: #f7f7f7;

font-family: &apos;Open Sans&apos;, sans-serif;

color: #333;

font-size: 16px;

line-height: 1.6; }
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This showed me that:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;font-family&lt;/code&gt; controls the typeface&lt;/p&gt;
&lt;p&gt;&lt;code&gt;font-size&lt;/code&gt; controls how big the text is&lt;/p&gt;
&lt;p&gt;&lt;code&gt;line-height&lt;/code&gt; controls spacing between lines&lt;/p&gt;
&lt;p&gt;&lt;code&gt;color&lt;/code&gt; sets the text color&lt;/p&gt;
&lt;p&gt;&lt;code&gt;background-color&lt;/code&gt; sets the page background&lt;/p&gt;
&lt;p&gt;I also learned about color contrast, which is important for accessibility. Text must be easy to read against the background. Tools like the WebAIM contrast checker helped me test my color choices.&lt;/p&gt;
&lt;h2&gt;Styling Headers&lt;/h2&gt;
&lt;p&gt;Next, I styled the headings (&lt;code&gt;h1&lt;/code&gt;, &lt;code&gt;h2&lt;/code&gt;, &lt;code&gt;h3&lt;/code&gt;) separately from the body text. This showed me how grouping selectors works. Instead of writing separate rules for each heading, I could apply the same style to all of them in one line. I also learned that modern websites usually use smaller headers than I expected. Looking at sites like Medium and Airbnb helped me understand that elegant design often comes from subtle sizing, not huge text.&lt;/p&gt;
&lt;h2&gt;Styling Links and Hover Effects&lt;/h2&gt;
&lt;p&gt;Links were another important part of the design. This introduced me to pseudo-classes, especially &lt;code&gt;:hover&lt;/code&gt;, which lets CSS react to user interaction. I also learned about motion sensitivity. If animations or transitions are added, they should respect users who prefer reduced motion.&lt;/p&gt;
&lt;h2&gt;Choosing Fonts and Color Schemes&lt;/h2&gt;
&lt;p&gt;To make the page look better, I explored:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Google Fonts&lt;/strong&gt; for typography&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Coolors&lt;/strong&gt; and &lt;strong&gt;Color Hunt&lt;/strong&gt; for color palettes&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For example, I imported fonts directly into my CSS file:&lt;/p&gt;
&lt;p&gt;@import url(&quot;&lt;a href=&quot;https://fonts.googleapis.com/css2?family=Open+Sans:wght@300;400;700&amp;amp;family=Poppins:wght@300;400;500;700&quot;&gt;https://fonts.googleapis.com/css2family=Open+Sans:wght@300;400;700&amp;amp;family=Poppins:wght@300;400;500;700&lt;/a&gt;&quot;);&lt;/p&gt;
&lt;p&gt;Then applied them, this taught me how external resources can be integrated into a project and controlled through CSS.&lt;/p&gt;
&lt;h2&gt;Working with the Box Model&lt;/h2&gt;
&lt;p&gt;The next step was to structure the page visually using the &lt;strong&gt;CSS box model&lt;/strong&gt;. I reorganised my HTML into grouped sections:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;div class=&quot;container&quot;&amp;gt;
&amp;lt;div class=&quot;card&quot;&amp;gt;&amp;lt;/div&amp;gt;

&amp;lt;div class=&quot;card&quot;&amp;gt;

&amp;lt;/div&amp;gt; &amp;lt;/div&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The &lt;code&gt;container&lt;/code&gt; keeps the page content centred, while each &lt;code&gt;card&lt;/code&gt; groups related information.&lt;/p&gt;
&lt;p&gt;I styled the container like this:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;.container {
width: 500px;

margin: 0 auto; }
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This showed me how &lt;code&gt;width&lt;/code&gt; controls the size of the layout and &lt;code&gt;margin: 0 auto&lt;/code&gt; centres the content horizontally.&lt;/p&gt;
&lt;h2&gt;Designing Cards&lt;/h2&gt;
&lt;p&gt;Each card became a white box with padding, rounded corners, and a soft shadow:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;.card {
background: white;

padding: 30px; border-radius:

5px; box-shadow: 0 0 10px rgba(0,0,0,0.1);

margin-bottom: 20px;

}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Here I learned how &lt;code&gt;padding&lt;/code&gt; creates space inside an element, &lt;code&gt;border-radius&lt;/code&gt; softens edges, &lt;code&gt;box-shadow&lt;/code&gt; adds depth &lt;code&gt;margin&lt;/code&gt; creates space between cards. This made the page look more like a real modern website instead of plain text on a background.&lt;/p&gt;
&lt;h2&gt;Learning Better CSS Selectors&lt;/h2&gt;
&lt;p&gt;A major lesson in this stage was learning how to name and organise CSS classes properly. It’s a better approach to use reusable classes. Therefore, we should use classes instead of IDs when styles can be reused. Choose names based on what the class does, not where it is and split styles into small reusable pieces instead of one giant rule.&lt;/p&gt;
&lt;h2&gt;Using the Browser Inspector&lt;/h2&gt;
&lt;p&gt;From this point onward, the browser inspector became essential. By right-clicking and choosing inspect, I could test CSS changes live, see which rules applied to which elements and experiment before writing final code. This made debugging and design much faster and helped me understand how CSS is actually interpreted by the browser.&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;Saving and Moving Forward&lt;/h2&gt;
&lt;p&gt;Once everything was styled and structured, I pushed my work to GitHub:&lt;/p&gt;
&lt;p&gt;git add .&lt;/p&gt;
&lt;p&gt;git commit -m &quot;Added fonts &amp;amp; colors to my profile page&quot;&lt;/p&gt;
&lt;p&gt;git push origin master&lt;/p&gt;
&lt;p&gt;Then I copied the project into the next exercise folder: cp -r profile ../filepath&lt;/p&gt;
&lt;p&gt;Later, after finishing the box model and selector improvements, I repeated the process.&lt;/p&gt;
&lt;h2&gt;Final Thoughts&lt;/h2&gt;
&lt;p&gt;Building and styling my profile page step by step helped me understand how HTML and CSS work together in practice. What started as a simple page with text and images gradually became a structured and styled layout using fonts, colors, the box model, and well-chosen selectors. This process taught me that good web design is not about adding as much styling as possible, but about making thoughtful choices that improve readability, accessibility, and reuse. Learning to organise my CSS with reusable classes, centre content with containers, and group information into cards gave me a much clearer idea of how real websites are built. Overall, this project showed me that even a small page can teach big lessons about structure, design, and maintainability, and it gave me the confidence to keep experimenting with CSS as I move on to more responsive and dynamic layouts.&lt;/p&gt;
</content:encoded><category>html</category><category>css</category><category>frontend</category><author>Bianca Correia</author></item><item><title>What I Learned About Active Record Migrations in Ruby</title><link>https://biancacorreia.com/blog/what-i-learned-about-active-record-migrations-in-ruby</link><guid isPermaLink="true">https://biancacorreia.com/blog/what-i-learned-about-active-record-migrations-in-ruby</guid><description>In this exercise, I learned how to use Active Record migrations to build the structure of a database using Ruby.</description><pubDate>Mon, 09 Feb 2026 23:43:25 GMT</pubDate><content:encoded>&lt;p&gt;In this exercise, I learned how to use &lt;strong&gt;Active Record migrations&lt;/strong&gt; to build the structure of a database using Ruby. Instead of writing SQL directly, migrations allow us to describe our database tables and columns with Ruby code.&lt;/p&gt;
&lt;p&gt;I needed to create a &lt;code&gt;posts&lt;/code&gt;table that can store links shared by users. The table needed a title, a URL, and timestamps.&lt;/p&gt;
&lt;p&gt;I also learned that migrations are only used to change the &lt;strong&gt;structure of the database&lt;/strong&gt;, not the data inside it.&lt;/p&gt;
&lt;p&gt;Migration files must follow a specific naming format:&lt;/p&gt;
&lt;p&gt;yyyymmddhhmmss_migration_name.rb&lt;/p&gt;
&lt;p&gt;For example:&lt;/p&gt;
&lt;p&gt;20260202152200_create_posts.rb&lt;/p&gt;
&lt;p&gt;The timestamp in the filename is important because it tells Active Record which migrations have already been run and which ones still need to run.&lt;/p&gt;
&lt;h2&gt;Creating the Posts Table&lt;/h2&gt;
&lt;p&gt;To create the &lt;code&gt;posts&lt;/code&gt; table, I wrote the following migration:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;class CreatePosts &amp;lt; ActiveRecord::Migration[8.1]
def change create_table :posts do |t|

t.string :title

t.string :url

t.timestamps

end
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This migration creates: a title column, a url column, created_at and update_at column using t.timestamps.&lt;/p&gt;
&lt;p&gt;The timestamp columns are useful because they record when a post is created and when it is updated.&lt;/p&gt;
&lt;p&gt;After writing the migration, I ran: rake db:migrate. Then I checked the database with: sqlite3 db/development.sqlite3 .schema.&lt;/p&gt;
&lt;p&gt;I noticed there were more tables than just my &lt;code&gt;posts&lt;/code&gt; table. These extra tables are created by Active Record and are used to keep track of migrations and manage the database internally.&lt;/p&gt;
&lt;h2&gt;Updating the Posts Table&lt;/h2&gt;
&lt;p&gt;Next, I created another migration to update the &lt;code&gt;posts&lt;/code&gt; table. I added a new column called &lt;code&gt;votes&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;I created a new migration file with a new timestamp and wrote the following code:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;class AddVotesToPosts &amp;lt; ActiveRecord::Migration[8.1]
def change add_column :posts, :votes, :integer, default: 0
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This migration added a votes column, with a type integer and a default value of 0.&lt;/p&gt;
&lt;p&gt;his means a post starts with zero votes when it is created.&lt;/p&gt;
&lt;p&gt;I then ran the migration again: rake db:migrate&lt;/p&gt;
&lt;p&gt;Now the &lt;code&gt;posts&lt;/code&gt; table contains title, url, created_at, updated_at and votes.&lt;/p&gt;
&lt;p&gt;In this exercise, I learned how to use Active Record migrations in Ruby to create and change the structure of a database. I created a &lt;code&gt;posts&lt;/code&gt; table for a Hacker News clone with columns for a title, a URL, and timestamp fields for &lt;code&gt;created_at&lt;/code&gt; and &lt;code&gt;updated_at&lt;/code&gt;. I also learned that migration files must be named using a timestamp so Active Record knows which migrations to run and in what order. After running &lt;code&gt;rake db:migrate&lt;/code&gt;, I checked the database schema and saw extra tables created by Active Record, which showed me that it also manages internal information about the database. Finally, I wrote another migration to update the table by adding a &lt;code&gt;votes&lt;/code&gt; column with a default value of 0, which helped me understand that migrations are used to change the database structure, not to insert data.&lt;/p&gt;
</content:encoded><category>ruby</category><category>rails</category><category>databases</category><author>Bianca Correia</author></item><item><title>How To Build a Store Interface Program</title><link>https://biancacorreia.com/blog/how-to-build-a-store-interface-program</link><guid isPermaLink="true">https://biancacorreia.com/blog/how-to-build-a-store-interface-program</guid><description>After the completion of one week, we were requested to build a store interface program that was the culmination of all we had learned throughout the first…</description><pubDate>Mon, 02 Feb 2026 23:53:30 GMT</pubDate><content:encoded>&lt;p&gt;After the completion of one week, we were requested to build a store interface program that was the culmination of all we had learned throughout the first week. This included arrays, hashes, loops,blocks, conditionals, variables, gets.chomp and puts for output.&lt;/p&gt;
&lt;p&gt;These on their own are quite straightforward but incorporating them all did present more of a challenge. The challenge was broken down in numerous steps which made it a little bit more digestible and enabled me to keep in top of the flow of the code and to better.&lt;/p&gt;
&lt;p&gt;In this blog, I’ll walk through how to build a very simple supermarket-style program in Ruby. Something that lets a user see items for sale, choose what they want, and then get a total bill at the end. More importantly, it helped me understand how real systems (like online shops) might work behind the scenes, just in a much simpler way.&lt;/p&gt;
&lt;h3&gt;Displaying a welcome message&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;puts &quot;&amp;gt; --------------------&quot;
puts &quot;&amp;gt; Welcome to Instacart&quot;
puts &quot;&amp;gt; --------------------&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Here we use &lt;code&gt;puts&lt;/code&gt; to print text to the terminal.&lt;/p&gt;
&lt;p&gt;This is purely for user experience. It makes the program feel like a real shop instead of just raw code. It also helps the user understand that the program has started. At first glance, this just looks like a list of items and prices. But conceptually, it acts like a tiny database. Each key is a product name, and each value is its price.&lt;/p&gt;
&lt;h3&gt;Creating the Shopping Cart&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;cart = []
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The cart is an empty &lt;code&gt;array&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Why an array?&lt;br /&gt;
Because we want to store multiple items that the user chooses, like:&lt;/p&gt;
&lt;p&gt;[&quot;banana&quot;, &quot;banana&quot;, &quot;kiwi&quot;]&lt;/p&gt;
&lt;p&gt;Each time the user selects something, we will push it into this cart array.&lt;/p&gt;
&lt;p&gt;Defining the Store with a &lt;code&gt;Hash&lt;/code&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;store = {
&quot;kiwi&quot; =&amp;gt; 1.25,
&quot;banana&quot; =&amp;gt; 0.5,
&quot;mango&quot; =&amp;gt; 4,
&quot;asparagus&quot; =&amp;gt; 9
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This is a hash, which stores key–value pairs:&lt;/p&gt;
&lt;p&gt;Key → item name (string)&lt;/p&gt;
&lt;p&gt;Value → price (number)&lt;/p&gt;
&lt;p&gt;For example:&lt;/p&gt;
&lt;p&gt;&quot;banana&quot; is the key&lt;/p&gt;
&lt;p&gt;0.5 is the value&lt;/p&gt;
&lt;p&gt;This makes it easy to look up prices later using:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;store[&quot;banana&quot;]
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Which would return: 0.5. It means: “Take the user’s input and use it as a key to fetch the price.” That’s a big conceptual leap as a beginner — I’m no longer just printing values, I’m now connecting user input to data structures. This also means all the prices live in one place. If I want to change the price of mango, I only need to change it in the hash, and the rest of the program still works. That’s something real systems rely on heavily.&lt;/p&gt;
&lt;h3&gt;Displaying Items for Sale&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;store.each do |item, price|
puts &quot;&amp;gt; #{item}: £#{price}&quot;
end
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Here we use .each to loop through the hash.&lt;/p&gt;
&lt;p&gt;For every item in the store, item holds the name (e.g. &quot;kiwi&quot;) and price holds the price (e.g. 1.25). This prints something like:&lt;/p&gt;
&lt;p&gt;kiwi: £1.25&lt;/p&gt;
&lt;p&gt;banana: £0.5&lt;/p&gt;
&lt;p&gt;mango: £4&lt;/p&gt;
&lt;p&gt;asparagus: £9&lt;/p&gt;
&lt;p&gt;So now the user can see what’s available before shopping.&lt;/p&gt;
&lt;h3&gt;Preparing for User Input&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;item = nil
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We initialised item so it exists before the loop starts. This is important because we are about to use it in a loop condition.&lt;/p&gt;
&lt;h3&gt;Creating the Shopping Loop&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;until item == “quit”
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This line is what makes the program feel “alive”.&lt;br /&gt;
Instead of running once and stopping, the program keeps going until the user decides to quit.&lt;/p&gt;
&lt;p&gt;This taught me that loops aren’t just for repeating actions — they allow the &lt;strong&gt;user&lt;/strong&gt; to control the flow of the program. The code is waiting for human input and reacting to it. In a way, the program becomes a conversation. This helped me understand that software is often built around user behaviour, not just calculations.&lt;/p&gt;
&lt;h3&gt;Asking the User for an Item&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;puts &quot;&amp;gt; Which item? (or &apos;quit&apos; to checkout)&quot;
item = gets.chomp
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;gets reads input from the user&lt;/p&gt;
&lt;p&gt;&lt;code&gt;.chomp&lt;/code&gt; removes the newline character at the end.&lt;/p&gt;
&lt;h3&gt;Checking If the Item Exists&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;if store.keys?(item)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This checks, is the user’s input one of the keys in the store hash?&lt;/p&gt;
&lt;p&gt;For example: “banana” —&amp;gt; true, “pizza” —→ false&lt;/p&gt;
&lt;p&gt;This prevents users from buying things that don’t exist.&lt;/p&gt;
&lt;h3&gt;Adding Valid Items to the Cart&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;cart &amp;lt; &amp;lt; items
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If the item exists, we add it to the cart array. So the cart might look like:&lt;/p&gt;
&lt;p&gt;[“banana”, “mango”, “banana” ]&lt;/p&gt;
&lt;p&gt;This allows duplicates, which is realistic for shopping.&lt;/p&gt;
&lt;h3&gt;Handling Invalid Items&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;elsif item != &apos;quit&apos;
puts &quot;sorry we don&apos;t have any #{item} today.&quot;
end
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If the user types something that is not in the store and is not &quot;quit&quot;, then we print an apology message. This introduces the idea of validation: never blindly trust user input. Instead of assuming the user will always type a valid product, the program verifies it against the data. So learning to guard against misspellings, unexpected values or mistakes that may be inputted early on is really useful.&lt;/p&gt;
&lt;h3&gt;Printing the Bill&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;puts &apos;&amp;gt; -------BILL---------&apos;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This marks the checkout stage of the program.&lt;/p&gt;
&lt;h3&gt;Calculating the Total Price&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;total_price = 0
cart.each do |item|

total_price += store[item]

end
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We start with total_price = 0, we loop through every item in the cart and for each item we look up the price in the store hash and add it to the total.&lt;/p&gt;
&lt;p&gt;for example, —→ [&quot;banana&quot;, &quot;mango&quot;] becomes 0 + 0.5 + 4 = 4.5.&lt;/p&gt;
&lt;p&gt;This taught me that loops aren’t just for printing — they’re for transforming data.&lt;br /&gt;
Here, an array of strings becomes one meaningful number: the total cost. It also connects multiple concepts at once: looping through an array, accessing a hash and updating a variable. Which makes it a good mental workout as a beginner.&lt;/p&gt;
&lt;h3&gt;Displaying the Final Total&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;puts &quot;&amp;gt; TOTAL: #{total_price} £&quot;
puts &quot;&amp;gt; --------------------&quot;rub
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This prints the final amount the user owes.&lt;/p&gt;
&lt;p&gt;Example output: Total: 4.5£&lt;/p&gt;
&lt;p&gt;This gives the program a proper ending and makes it feel complete.&lt;/p&gt;
&lt;p&gt;I found that this store interface was a great beginner project because it felt practical and real. It simulates how real systems work: choosing products, validating input, and calculating totals. Beyond syntax,t his project taught me how arrays and hashes work together, user input connects to program login, data drives decisions and small programs can model real systems.&lt;/p&gt;
&lt;p&gt;It was a great way to practice thinking in terms of data and flow rather than just individual lines of code.&lt;/p&gt;
</content:encoded><category>ruby</category><author>Bianca Correia</author></item><item><title>What I Learned About Hashes and Symbols in Ruby</title><link>https://biancacorreia.com/blog/what-i-learned-about-hashes-and-symbols-in-ruby</link><guid isPermaLink="true">https://biancacorreia.com/blog/what-i-learned-about-hashes-and-symbols-in-ruby</guid><description>As I continue learning Ruby, one of the most important concepts I have encountered is the use of hashes and symbols.</description><pubDate>Mon, 26 Jan 2026 23:08:17 GMT</pubDate><content:encoded>&lt;p&gt;As I continue learning Ruby, one of the most important concepts I have encountered is the use of hashes and symbols. At first, these ideas felt confusing, particularly because of the unfamiliar syntax and the different ways data could be accessed. However, with practice and repeated exposure, I have come to understand how essential they are for organising and managing information within a Ruby program.&lt;/p&gt;
&lt;p&gt;Over time (and after breaking my code a few times ), I realised that hashes and symbols are actually some of the most useful tools in Ruby. They help organise data in a clean way and make code easier to read once you understand them.&lt;/p&gt;
&lt;p&gt;What is a Hash?&lt;/p&gt;
&lt;p&gt;A hash is a way to store data using key values.&lt;br /&gt;
I like to think of it like a mini database or a dictionary inside my program.This structure is especially useful when working with related pieces of data that need to be accessed by name rather than by position, as is the case with arrays.&lt;/p&gt;
&lt;p&gt;Here, “name” and “age” are keys, “Ana” and 25 are values.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;person = {
“name” =&amp;gt; “Ana”,

“age” =&amp;gt; 25
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Instead of remembering positions like in an array, I can just ask for what I want by name:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;person [“name”]
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This returns “Ana”,&lt;/p&gt;
&lt;p&gt;At first, I used strings as keys in my hashes. Then I started seeing this everywhere:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;person = {
name: “Ana”,

age: 25
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I didn’t understand why there was no arrow (&lt;code&gt;=&amp;gt;&lt;/code&gt;) and why the keys didn’t have quotes.&lt;br /&gt;
This is when I learned about symbols. A symbol is a lightweight, immutable identifier that is often used in place of strings, particularly as hash keys.&lt;/p&gt;
&lt;p&gt;A symbol looks like this, and it’s different from a string:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;:name
:age
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Even though they look similar, Ruby treats them differently. Although they appear similar, strings and symbols are not interchangeable. If a hash uses symbols as keys, the values must be accessed using symbols as well. A big lesson for me was realising that this will not work:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;person [“name”]
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;if the key is a symbol, that small detail caused me a lot of nil errors until it finally clicked.&lt;/p&gt;
&lt;p&gt;Hashes in Ruby are mutable, meaning that their contents can be changed after creation.&lt;/p&gt;
&lt;p&gt;Adding new data:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;person[:job] = “Accountant”
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Updating existing data:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;person[:age] = 26
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This made hashes feel more realistic to me, like real user data that can change.&lt;/p&gt;
&lt;p&gt;One mistake I kept making was mixing up symbols and strings:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;user = { name: “Ana” }
user[”name”] # nil
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The correct way:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;user[:name]
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Hashes can be iterated over using the .each method, which provides access to both the key and the value:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;person.each do |key, value|
puts “The #{key} is #{value}”
end
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Iteration makes it possible to process or display all the data stored in a hash in a structured manner.&lt;/p&gt;
&lt;p&gt;The main points I have learned is that symbols are faster than strings, more memory efficient and meant for things that don’t change (like keys).&lt;/p&gt;
&lt;p&gt;Hashes and symbols were confusing at first, but now they feel like one of the most useful parts of Ruby. They helped me move from writing very simple programs to working with structured data. They still take practice, but now when I see a hash full of symbols, it doesn’t feel scary anymore — it feels familiar. And that, for me, is progress.&lt;/p&gt;
</content:encoded><category>ruby</category><author>Bianca Correia</author></item><item><title>What I Learned From My First Ruby Backend Challenge</title><link>https://biancacorreia.com/blog/what-i-learned-from-my-first-ruby-backend-challenge</link><guid isPermaLink="true">https://biancacorreia.com/blog/what-i-learned-from-my-first-ruby-backend-challenge</guid><description>Starting my first backend coding challenge with Ruby was honestly a mix of excitement, confusion, and a lot of “wait… what?” moments .</description><pubDate>Mon, 26 Jan 2026 23:04:04 GMT</pubDate><content:encoded>&lt;p&gt;Starting my first backend coding challenge with Ruby was honestly a mix of excitement, confusion, and a lot of “wait… what?” moments . As a complete beginner, this was my first real experience writing backend code, and while it felt intimidating at times, it was also incredibly rewarding. This challenge helped me understand the basics of Ruby and reminded me that learning to code is all about taking things one step at a time.&lt;/p&gt;
&lt;p&gt;Here’s what I learned from my very first Ruby backend challenge.&lt;/p&gt;
&lt;p&gt;One of the first things I learned is that in Ruby we use the # symbol to write comments. Comments don’t affect how the code runs, but they are super helpful for us as beginners. I quickly started using them like a little &lt;em&gt;to-do list&lt;/em&gt; or reminders to explain what my code was supposed to do.&lt;/p&gt;
&lt;p&gt;I also learned about Ruby keycodes which tell the computer what action to take. One of the first ones I used being ‘puts’ which prints information to the terminal.Seeing my code actually print something on the screen felt like a small win, but a win nonetheless.&lt;/p&gt;
&lt;p&gt;I learned that data types describe the data type we’re working with. Some I came across were integers, float, strings booleans mainly. At first, this was a bit confusing, but understanding data types helped me make sense of errors and understand why my code behaved the way it did.&lt;/p&gt;
&lt;p&gt;I also learned that Ruby can handle basic maths like addition, subtraction, multiplication and division.&lt;/p&gt;
&lt;p&gt;As soon as my programs started growing, I realised I needed a way to store more than one piece of data at a time. That’s where data structures come in. The main one I have learnt so far is array.&lt;/p&gt;
&lt;p&gt;The challenge included experimenting with built‑in methods for different data types and then we had to also find other methods that were not built in.&lt;/p&gt;
&lt;p&gt;This first Ruby backend challenge taught me that it’s okay not to understand everything straight away. I learned that backend development isn’t about being perfect — it’s about practising, making mistakes, and slowly improving.&lt;/p&gt;
&lt;p&gt;I’m still very much a beginner, but this challenge made Ruby feel a little less scary and a lot more exciting. I’m looking forward to learning more, writing more code, and trusting the process — one line at a time&lt;/p&gt;
</content:encoded><category>ruby</category><author>Bianca Correia</author></item><item><title>Early Days</title><link>https://biancacorreia.com/blog/early-days</link><guid isPermaLink="true">https://biancacorreia.com/blog/early-days</guid><description>I’m excited to share that I’ve officially joined Le Wagon and have started working through the prep work ahead of the course.</description><pubDate>Mon, 26 Jan 2026 22:58:46 GMT</pubDate><content:encoded>&lt;p&gt;I’m excited to share that I’ve officially joined Le Wagon and have started working through the prep work ahead of the course. This marks the beginning of a new chapter for me. One that is focused on learning, buildings and pushing myself outside my comfort zone. which historically, has always paid off, in new experiences, growth and lessons.&lt;/p&gt;
&lt;p&gt;Before the bootcamp officially kicks off, I was provided by Le Wagon a set or prep exercises to get comfortable with he basics. It seems that early curiosity with writing code has paid off, as everything I have leant a few summers ago have come in handy,&lt;/p&gt;
&lt;p&gt;One of the first tasks at the end of the first module was to create a personal profile about myself from scratch. Seeing how headings, paragraphs , images and sections come together made my page feel a lot more approachable and alive.&lt;/p&gt;
&lt;p&gt;Another key part of the task was using an unordered lis. I used this to highlight things like my interests, It was a simple feature, but it really showed me how HTML helps organize content in a clean and readable way. I also added a link which was cool to add a little of interconnectivity to the profile.&lt;/p&gt;
&lt;p&gt;This prep work has already taught my a lot:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;How HTML provides structure to web content&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;How small elements like lists and links improve usability&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;How satisfying it is to build something from scratch&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Learning to code is much about experimenting as it s about the rules&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Even though the page was simple, it gave me a real sense of progress and confidence. I wasn’t just following instructions, I was creating something as a result of taking in that knowledge from the module.&lt;/p&gt;
&lt;p&gt;This is only the beginning of my journey with Le Wagon, I’m looking forward to diving deeper int o web development, learning new languages and continuing to build projects that challenge me. For now, I’m proud of my first HTML page and excited for what is next. Onward and upward!✌🏽&lt;/p&gt;
</content:encoded><category>career-change</category><category>le-wagon</category><author>Bianca Correia</author></item></channel></rss>