<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Saribeg</title>
    <description>The latest articles on DEV Community by Saribeg (@saribeg).</description>
    <link>https://dev.to/saribeg</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3490055%2Fea2321b3-c2c4-4d21-86b7-533647f31952.png</url>
      <title>DEV Community: Saribeg</title>
      <link>https://dev.to/saribeg</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/saribeg"/>
    <language>en</language>
    <item>
      <title>Full Stack Open Course: My Experience with Part 8 (GraphQL)</title>
      <dc:creator>Saribeg</dc:creator>
      <pubDate>Sat, 20 Dec 2025 11:06:17 +0000</pubDate>
      <link>https://dev.to/saribeg/full-stack-open-course-my-experience-with-part-8-graphql-kei</link>
      <guid>https://dev.to/saribeg/full-stack-open-course-my-experience-with-part-8-graphql-kei</guid>
      <description>&lt;p&gt;After wrapping up &lt;a href="https://dev.to/saribeg/full-stack-open-course-my-experience-with-parts-0-7-2f5k"&gt;Parts 0-7 of Full Stack Open&lt;/a&gt; with two different implementations of the BlogApp (&lt;a href="https://fso-blog-app.vercel.app/" rel="noopener noreferrer"&gt;Redux vs React Query&lt;/a&gt;), I was ready for something new. Enter &lt;a href="https://fullstackopen.com/en/part8" rel="noopener noreferrer"&gt;Part 8: GraphQL&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If you've been following the MERN stack journey in my &lt;a href="https://dev.to/saribeg/full-stack-open-course-my-experience-with-parts-0-7-2f5k"&gt;previous articles&lt;/a&gt;, you know I'm all about diving deep and going beyond the minimum requirements. Part 8 was no exception - and honestly, GraphQL turned out to be both fascinating and frustrating in ways I didn't expect.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;a href="https://github.com/Saribeg/Full-Stack-Open/tree/main/Part-8" rel="noopener noreferrer"&gt;Repository folder with codebase&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Why GraphQL?
&lt;/h2&gt;

&lt;p&gt;Before jumping in, let's address the elephant in the room: REST APIs work perfectly fine for most applications. So why learn GraphQL?&lt;/p&gt;

&lt;p&gt;The course materials make a compelling case: GraphQL solves the over-fetching and under-fetching problems inherent in REST. Instead of hitting multiple endpoints or getting back data you don't need, you ask for exactly what you want in a single request.&lt;/p&gt;

&lt;p&gt;Sounds great in theory. But theory and practice are two very different beasts.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Part 8 Covers
&lt;/h2&gt;

&lt;p&gt;The project is a deliberately simple library-style application, built to explore GraphQL fundamentals - authors, books, genres, the usual suspects. Here's what the course teaches:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;GraphQL server with Apollo Server&lt;/strong&gt; - schemas, resolvers, queries, mutations&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;React frontend with Apollo Client&lt;/strong&gt; - querying data, managing cache&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;MongoDB integration&lt;/strong&gt; - because GraphQL still needs to get data from somewhere&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Authentication with JWT&lt;/strong&gt; - protecting mutations behind login&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Subscriptions&lt;/strong&gt; - real-time updates via WebSocket&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The course exercises took me about &lt;strong&gt;20 hours&lt;/strong&gt;. But here's where it gets interesting: I spent an additional &lt;strong&gt;15+ hours&lt;/strong&gt; implementing features that weren't required but felt necessary for a real-world application.&lt;/p&gt;

&lt;p&gt;Let me explain why.&lt;/p&gt;

&lt;h2&gt;
  
  
  Beyond the Exercises: Where Things Got Real
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Pagination - When the Cache Has a Mind of Its Own
&lt;/h3&gt;

&lt;p&gt;Here’s where I made my first ‘creative’ decision: the course doesn’t cover pagination. Not content with adding it like a reasonable person, I decided to spice things up by implementing both approaches. Because why solve one problem when you can create two?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Offset-based pagination&lt;/strong&gt; for the Authors page (the traditional "page 1, 2, 3" approach)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cursor-based pagination&lt;/strong&gt; for Books with infinite scroll (like social media feeds)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The offset approach was straightforward - nothing too surprising there. But cursor-based pagination with infinite scroll? That's where Apollo Client's cache became... interesting.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The problem:&lt;/strong&gt; When you're loading more items incrementally (load 30 books, scroll down, load 30 more), Apollo needs to remember what you've already fetched and append new results. Easy, right? Not quite.&lt;/p&gt;

&lt;p&gt;Apollo Client caches data in a normalized way - think of it like a smart database that stores each object once and references it elsewhere. When I added real-time subscriptions (so new books would appear instantly when added by other users), the cache got confused about how to merge the new data with the existing paginated list.&lt;/p&gt;

&lt;p&gt;New books wouldn't appear. Or they'd appear twice. Or the cache would just forget chunks of data entirely.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why this happens:&lt;/strong&gt; Apollo provides mechanisms for merging paginated data, but when you combine custom merge strategies with real-time updates, you need to explicitly tell Apollo: "Hey, this new book reference goes here in the list, check if it already exists first, and update these specific query results."&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The solution:&lt;/strong&gt; Instead of letting Apollo's default behavior handle it, I had to manually update the cache whenever a new book arrived. This meant checking if the book already existed (to avoid duplicates), creating a proper reference to it (not embedding the whole object), and inserting it at the right position in the paginated list.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Lesson learned:&lt;/strong&gt; Apollo's cache is incredibly powerful, but it requires you to think about data as references and relationships, not just objects. When in doubt, the Apollo DevTools cache inspector became my best friend - seeing the actual cache structure helped me understand what was going wrong.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Custom Scalars - Validation That Makes Sense
&lt;/h3&gt;

&lt;p&gt;The course uses basic types: strings, numbers, booleans. But in a real application, you want more specific validation.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The idea:&lt;/strong&gt; GraphQL lets you define custom data types (called "scalars") that validate input automatically. Instead of accepting any string for a username, you can create a &lt;code&gt;Username&lt;/code&gt; type that only accepts alphanumeric characters between 3-15 characters long.&lt;/p&gt;

&lt;p&gt;I added custom scalars for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;Year&lt;/code&gt; - ensures it's a valid 4-digit year (not 99999 or -500)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Username&lt;/code&gt; - enforces formatting rules&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Password&lt;/code&gt; - sets length requirements before hashing&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Genre&lt;/code&gt; - normalizes to lowercase, prevents weird formatting&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Why this matters:&lt;/strong&gt; Validation happens at the GraphQL layer before your data even reaches the database. If someone tries to add a book published in year 3000, GraphQL rejects it immediately with a clear error message. Time travelers will need to use a different API. No need to write validation logic in multiple places - it's baked into the schema itself.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The challenge:&lt;/strong&gt; GraphQL's built-in scalars are limited, so you have to define custom ones yourself. But once set up, they work everywhere automatically - queries, mutations, even in nested objects.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Error Handling - Making Sense of What Went Wrong
&lt;/h3&gt;

&lt;p&gt;In REST APIs, you have HTTP status codes: 400 for bad request, 401 for unauthorized, 500 for server error. Simple.&lt;/p&gt;

&lt;p&gt;In GraphQL, every request returns HTTP 200, even when things go wrong. Error details live inside the response body under an &lt;code&gt;errors&lt;/code&gt; array.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The problem:&lt;/strong&gt; Different types of errors (validation errors, authentication errors, database errors) all look similar to the frontend unless you explicitly categorize them.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;My approach:&lt;/strong&gt; Following the sacred DRY principle and my personal vendetta against scattered error handling, I created a central error formatting function on the server that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Catches database validation errors (like duplicate usernames)&lt;/li&gt;
&lt;li&gt;Transforms them into clear, user-friendly messages&lt;/li&gt;
&lt;li&gt;Adds proper error codes (like &lt;code&gt;BAD_USER_INPUT&lt;/code&gt; or &lt;code&gt;UNAUTHENTICATED&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Hides internal server details from the client&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;On the frontend, I doubled down on this strategy with an error handling pipeline that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Intercepts all GraphQL errors globally&lt;/li&gt;
&lt;li&gt;Shows user-friendly toast notifications&lt;/li&gt;
&lt;li&gt;Automatically logs out users when authentication expires&lt;/li&gt;
&lt;li&gt;Retries failed requests for network issues (but not for bad input)&lt;/li&gt;
&lt;li&gt;Prevents duplicate error messages from spamming the user (a deceptively simple bullet point that cost me time wondering, “why is this toast appearing three times?!”)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Why this matters:&lt;/strong&gt; Without proper error handling, users see cryptic messages like "E11000 duplicate key error" instead of "This username is already taken." Good error handling is the difference between a confusing app and a polished one.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. The N+1 Query Problem - Efficiency at Scale
&lt;/h3&gt;

&lt;p&gt;Here's a sneaky performance issue that GraphQL makes easy to create: the N+1 query problem.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Scenario:&lt;/strong&gt; You want to show a list of 20 authors, each with their book count.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Naive approach:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Query the database for 20 authors (1 query)&lt;/li&gt;
&lt;li&gt;For each author, query the database for their books (20 queries)&lt;/li&gt;
&lt;li&gt;Total: 21 database queries&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If you have 100 authors, that's 101 queries. Yikes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The solution: DataLoader&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;DataLoader is a utility that batches requests. Instead of making 20 separate "get books for this author" queries, it collects all the author IDs, makes ONE query to get book counts for all authors at once, then distributes the results back to the right resolvers.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Result:&lt;/strong&gt; 21 queries become 2 queries. On large datasets, this is the difference between a snappy UI and a sluggish one.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why GraphQL makes this tricky:&lt;/strong&gt; Because GraphQL lets clients request nested data flexibly, it's easy to accidentally create these N+1 scenarios without realizing it. REST APIs force you to think about this upfront because you're designing specific endpoints.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Security - Protecting Your API
&lt;/h3&gt;

&lt;p&gt;The course doesn't cover GraphQL security, but here's the thing: GraphQL's flexibility is also a potential attack vector.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Problems that don't exist in REST:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Deeply nested queries:&lt;/strong&gt; Someone could request books → authors → books → authors → books... 50 levels deep, crashing your server&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Expensive queries:&lt;/strong&gt; A client could request every field on every object in your entire database in a single query&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Schema introspection:&lt;/strong&gt; By default, anyone can query your GraphQL schema to see every available field and type - like having your API documentation publicly available to attackers&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;My security additions:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Query depth limiting:&lt;/strong&gt; Reject queries nested deeper than 5 levels&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Query cost analysis:&lt;/strong&gt; Assign "costs" to different fields and reject queries that exceed a budget&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Introspection toggle:&lt;/strong&gt; Disable schema introspection in production&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Why this matters:&lt;/strong&gt; These attacks are specific to GraphQL's flexibility. A REST API naturally limits what clients can request because each endpoint is fixed. In GraphQL, you have to enforce these limits explicitly.&lt;/p&gt;

&lt;h3&gt;
  
  
  6. Database Aggregations - When Abstractions Break
&lt;/h3&gt;

&lt;p&gt;Here's a fun quirk I discovered: When using Mongoose (MongoDB library), there are two ways to query data:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Regular queries&lt;/strong&gt; - Mongoose handles everything nicely, transforms your data automatically&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Aggregation pipelines&lt;/strong&gt; - You write raw MongoDB queries for complex operations&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;For the Authors page, I wanted to sort authors by book count. This required using aggregation pipelines because I needed to count related books and sort by that count.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The surprise:&lt;/strong&gt; All the nice automatic data transformations Mongoose does (like converting MongoDB's &lt;code&gt;_id&lt;/code&gt; to &lt;code&gt;id&lt;/code&gt; via Mongoose’s &lt;code&gt;toJSON&lt;/code&gt; transform) don't happen in aggregation pipelines. Suddenly, my GraphQL queries expected an &lt;code&gt;id&lt;/code&gt; field, but the database was returning &lt;code&gt;_id&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The fix:&lt;/strong&gt; I had to manually specify the field transformation in the aggregation pipeline itself.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Lesson learned:&lt;/strong&gt; Abstractions are great until they're not. Sometimes you need to understand what's happening under the hood, especially when performance optimizations take you outside the happy path.&lt;/p&gt;

&lt;h2&gt;
  
  
  GraphQL vs REST: My Honest Take
&lt;/h2&gt;

&lt;p&gt;After spending 35+ hours with GraphQL, here's what I think:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;GraphQL shines when:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You have complex, interconnected data (think social networks, content platforms)&lt;/li&gt;
&lt;li&gt;Different clients (web, mobile, desktop) need different data subsets&lt;/li&gt;
&lt;li&gt;You want a strongly-typed contract between frontend and backend&lt;/li&gt;
&lt;li&gt;Real-time updates are important&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;REST is still better when:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Your API is straightforward CRUD operations&lt;/li&gt;
&lt;li&gt;You want to leverage standard HTTP caching (GraphQL usually uses a single POST endpoint, which makes CDN and browser-level caching much harder)&lt;/li&gt;
&lt;li&gt;Simplicity matters more than flexibility&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;GraphQL isn't magic - it's a trade-off. You exchange REST's simplicity for flexibility and type safety, but you pay for it with increased complexity in caching, error handling, and security.&lt;/p&gt;

&lt;h2&gt;
  
  
  Time Breakdown
&lt;/h2&gt;

&lt;p&gt;Here's how those 35 hours broke down:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Task&lt;/th&gt;
&lt;th&gt;Time&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Course material (Parts 8a-8e)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;20h 3m&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Custom scalars &amp;amp; validation&lt;/td&gt;
&lt;td&gt;1h 40m&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Pagination (offset + cursor-based)&lt;/td&gt;
&lt;td&gt;7h 42m&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Error handling &amp;amp; bug fixes&lt;/td&gt;
&lt;td&gt;4h 12m&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Security (depth/cost limits)&lt;/td&gt;
&lt;td&gt;1h 15m&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Total&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;35h 17m&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;That pagination time? Most of it was debugging cache issues and reading Apollo documentation to understand &lt;em&gt;why&lt;/em&gt; things weren't working.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's Next?
&lt;/h2&gt;

&lt;p&gt;The Full Stack Open course continues with CI/CD, containers, and more. I’ll probably write about other parts in future articles.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Want to see the code?&lt;/strong&gt; Check out my &lt;a href="https://github.com/Saribeg/Full-Stack-Open/tree/main/Part-8" rel="noopener noreferrer"&gt;GitHub repository&lt;/a&gt; with the full implementation, including all the extra features I added.&lt;/p&gt;

&lt;p&gt;Have you worked with GraphQL? What was your experience? Drop a comment — I’m curious how it played out for you.&lt;/p&gt;

&lt;p&gt;Happy coding. 😉&lt;/p&gt;

</description>
      <category>graphql</category>
      <category>learning</category>
      <category>javascript</category>
      <category>fullstack</category>
    </item>
    <item>
      <title>Full Stack Open Course: My Experience with Parts 0-7</title>
      <dc:creator>Saribeg</dc:creator>
      <pubDate>Tue, 30 Sep 2025 14:10:07 +0000</pubDate>
      <link>https://dev.to/saribeg/full-stack-open-course-my-experience-with-parts-0-7-2f5k</link>
      <guid>https://dev.to/saribeg/full-stack-open-course-my-experience-with-parts-0-7-2f5k</guid>
      <description>&lt;p&gt;After spending several years deep in the e-commerce trenches with Salesforce Commerce Cloud, I found myself craving something different. Not just another JavaScript framework tutorial or a "build a todo app in 10 minutes" speedrun, but a proper, comprehensive deep dive - not into the unknown, but into refreshing what I already knew and discovering new corners of full-stack JavaScript.&lt;/p&gt;

&lt;p&gt;That's when I stumbled upon &lt;a href="https://fullstackopen.com/en/" rel="noopener noreferrer"&gt;&lt;strong&gt;Full Stack Open&lt;/strong&gt;&lt;/a&gt; from the University of Helsinki.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why This Course Hit Different
&lt;/h2&gt;

&lt;p&gt;Let's be real - the internet is drowning in coding courses. So what made FSO stand out?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;University-backed quality&lt;/strong&gt;: This isn't someone's weekend project. It's an actual university course, taught by professors who know their stuff&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;University-recognized credits&lt;/strong&gt;: You can earn real &lt;strong&gt;ECTS credits&lt;/strong&gt; through the University of Helsinki’s Open University - formal European university credits that may count toward degree studies, or simply serve as official proof of your learning via transcript.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The price tag&lt;/strong&gt;: Free. Completely. No "premium" upsells, no paywalls after lesson 3&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;After years of fragmented tutorials and "just trust me bro" explanations, finding a structured, academic approach felt like discovering clean code after debugging spaghetti for hours.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's Actually in Parts 0-7?
&lt;/h2&gt;

&lt;p&gt;These first seven parts focus on the &lt;strong&gt;MERN stack&lt;/strong&gt; and give you enough knowledge to start contributing to real-world projects:&lt;/p&gt;

&lt;h3&gt;
  
  
  The Tech Stack:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Frontend&lt;/strong&gt;: React, Redux, React Query (because state management debates never get old)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Backend&lt;/strong&gt;: Node.js, Express, MongoDB, REST APIs, JWT authentication&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Testing&lt;/strong&gt;: The whole spectrum - unit tests with Vitest, integration tests with SuperTest, E2E with both Playwright and Cypress&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Deployment&lt;/strong&gt;: To cloud PaaS platforms like Render and Fly.io (goodbye, localhost:3000!)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The course includes around &lt;strong&gt;153 exercises&lt;/strong&gt;, but here's the beautiful part: there's no ceiling. Complete the basics? Great, you pass. Want to go deeper and polish every edge case? The playground is yours.&lt;/p&gt;

&lt;h2&gt;
  
  
  How I Approached the Course
&lt;/h2&gt;

&lt;p&gt;Since I wasn't completely new to these technologies, I decided to challenge myself:&lt;/p&gt;

&lt;h3&gt;
  
  
  Part 5 - The Testing Showdown
&lt;/h3&gt;

&lt;p&gt;Instead of picking one E2E framework, I implemented tests in both &lt;strong&gt;Playwright&lt;/strong&gt; and &lt;strong&gt;Cypress&lt;/strong&gt;. Nothing teaches you the pros and cons of each tool quite like writing the same test suite twice.&lt;/p&gt;

&lt;h3&gt;
  
  
  Part 7 - The Ultimate Comparison
&lt;/h3&gt;

&lt;p&gt;I built the final BlogApp project twice with different tech stacks:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;a href="https://blogs-redux-fso.vercel.app/about" rel="noopener noreferrer"&gt;&lt;strong&gt;Redux Toolkit + TailwindCSS&lt;/strong&gt;&lt;/a&gt; (for that utility-first satisfaction)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://blogs-query-fso.vercel.app/about" rel="noopener noreferrer"&gt;&lt;strong&gt;React Query + Material-UI&lt;/strong&gt;&lt;/a&gt; (because sometimes you want components that just work)&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  🚀 &lt;strong&gt;Check Out the Demo&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Want to see the code in action? I built a dedicated landing page with details about the project, the tech stack, and even time-tracking logs. There you’ll find links to both versions of the app, which you can try out. Each version also includes an &lt;em&gt;About&lt;/em&gt; page with technical notes, design choices, my impressions and other details.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;a href="https://fso-blog-app.vercel.app" rel="noopener noreferrer"&gt;🌐 Demo App&lt;/a&gt;
&lt;/h3&gt;

&lt;h3&gt;
  
  
  &lt;a href="https://github.com/Saribeg/Full-Stack-Open" rel="noopener noreferrer"&gt;📦 GitHub Repository&lt;/a&gt;
&lt;/h3&gt;




&lt;h2&gt;
  
  
  Who Should Take This Course?
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Developers who already know JS/React and want to see the full picture of full-stack development.&lt;/li&gt;
&lt;li&gt;Anyone who wants to brush up on their full-stack skills.&lt;/li&gt;
&lt;li&gt;Those who value a structured roadmap and the bonus of earning university credits.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What the Course Doesn't Cover (Yet)
&lt;/h2&gt;

&lt;p&gt;Let's keep it real - no course is perfect. Here's what you might want to supplement:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Redux thunks and custom middleware&lt;/strong&gt; aren't covered. You'll want to explore these for handling complex async flows and error boundaries&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Caching strategies&lt;/strong&gt; get a surface-level treatment. In production, this becomes critical (and no, you can't just memorize it - experiment and break things!)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Advanced authentication patterns&lt;/strong&gt; like refresh tokens, session management, and token rotation are left as "exercises for the reader"&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I ended up implementing database seeding for demo environments - not required, but incredibly useful for testing and showcasing your work. But I left some features untouched - the infinite like counter stayed as is. Let’s just call it an artistic choice.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Golden Rule
&lt;/h2&gt;

&lt;p&gt;Don't rush through it like you're cramming for an exam. Use FSO as your foundation, then build on top of it with what you actually need in your day-to-day work. The course gives you the blueprint; you're the architect.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's Next?
&lt;/h2&gt;

&lt;p&gt;Maybe later I’ll also write about other parts I’ve completed - for example, GraphQL, CI/CD, and Docker. Each part adds another layer to your full-stack toolkit.&lt;/p&gt;

&lt;p&gt;For now, if you're looking to build a rock-solid foundation in the MERN stack with proper testing and easy (non-DevOps) deployment practices, Parts 0-7 are your launchpad.&lt;/p&gt;

&lt;p&gt;Happy coding, and remember: &lt;code&gt;console.log()&lt;/code&gt; is a perfectly valid debugging strategy, no matter what anyone tells you. 😉&lt;/p&gt;




&lt;h3&gt;
  
  
  💬 Share Your Experience
&lt;/h3&gt;

&lt;p&gt;Have you taken Full Stack Open? What was your experience? Drop a comment below - I'd love to hear about your approach to the exercises!&lt;/p&gt;

</description>
      <category>fullstack</category>
      <category>learning</category>
      <category>javascript</category>
      <category>webdev</category>
    </item>
    <item>
      <title>The Developer’s Learning Journey: When Study Methods Evolve Over Time</title>
      <dc:creator>Saribeg</dc:creator>
      <pubDate>Thu, 11 Sep 2025 06:46:59 +0000</pubDate>
      <link>https://dev.to/saribeg/the-developers-learning-journey-when-study-methods-evolve-over-time-55i5</link>
      <guid>https://dev.to/saribeg/the-developers-learning-journey-when-study-methods-evolve-over-time-55i5</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fh9aylq3ewpqg2ye2t44a.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fh9aylq3ewpqg2ye2t44a.png" alt="Programming meme" width="800" height="960"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“Live as if you were to die tomorrow. Learn as if you were to live forever.” - Mahatma Gandhi&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In tech, you never stop learning. But the way you learn changes over time. What feels perfect at the beginning can become a roadblock a few years later.&lt;/p&gt;

&lt;p&gt;This is my personal story of how my learning stack evolved from in-person IT school to video courses, from reading the docs while building pet projects to structured, practice-heavy programs, and finally to a cautious relationship with AI.&lt;/p&gt;

&lt;p&gt;If you recognize yourself in any of this, you’re not alone.&lt;/p&gt;

&lt;h2&gt;
  
  
  Stage 1: IT Bootcamps (IT School) as a Beginner’s Compass (2018)
&lt;/h2&gt;

&lt;p&gt;Coming from a completely different field, I needed three things that self-study couldn't provide:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Structure&lt;/strong&gt; - a clear, well-designed curriculum with the right topics in the right order.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Support&lt;/strong&gt; - mentors and instructors you can turn to when you’re stuck - they can unblock you and help you move forward.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Community&lt;/strong&gt; of peers - fellow strugglers who understood why a missing semicolon could ruin your entire evening.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;At this stage, scattered video tutorials and mini-courses on individual technologies felt like trying to build a house by randomly collecting bricks. They lacked the comprehensive, systematic approach I needed.&lt;/p&gt;

&lt;p&gt;The bootcamp (in my case, an IT school program) became the obvious choice. In-person attendance added the necessary atmosphere and drive - there's something about physically showing up that makes you take it seriously. Team projects with coursemates and a community to discuss solutions accelerated the process exponentially. Nothing beats the "aha!" moment when you explain your bug to someone and suddenly realize the solution mid-sentence.&lt;/p&gt;

&lt;p&gt;That's how I entered the programming world through a Full-Stack JavaScript Developer program. Back then, React was still written with class components! 😄 (For the younger folks reading this - yes, we used to write &lt;code&gt;componentDidMount&lt;/code&gt; and &lt;code&gt;this.setState&lt;/code&gt; everywhere, and we liked it... sort of.)&lt;/p&gt;

&lt;p&gt;IT bootcamps provide an excellent foundation and smooth entry into the profession - ideal for first steps. But once you understand the landscape, you're ready for independent exploration. Later, returning to a bootcamp for new topics feels like overkill. My university education had already given me the necessary skills for finding and analyzing information; I just needed that initial push into the profession.&lt;/p&gt;

&lt;p&gt;This realization made me reconsider video courses. Platforms like Udemy - what hadn't worked at the very beginning suddenly became the perfect tool.&lt;/p&gt;

&lt;h2&gt;
  
  
  Stage 2: Video Tutorials - Quick Immersion (First 2 Years of Experience)
&lt;/h2&gt;

&lt;p&gt;When you're learning a technology for the first time without similar experience to lean on, visual and sequential information delivery with step-by-step explanations is perfect for comprehension. You diligently follow the instructor, implement course projects, add your own touches. Eventually, the information sticks. It's a fast way to master new tools without significant investment.&lt;/p&gt;

&lt;p&gt;I consumed countless hours on Udemy and similar platforms. Topics ranged from advanced Node.js concepts in my early days to TypeScript and GraphQL as I gained experience.&lt;/p&gt;

&lt;p&gt;But as my knowledge grew, this format suddenly stopped working. I discovered several pain points:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;The Illusion of Understanding&lt;/strong&gt;. Everything makes sense immediately. No need to type the code in your IDE - it all seems simple and obvious. This completely kills effectiveness. Learning must happen through practice, not passive watching. It's not about laziness; it's about blind confidence that "I get it." Result? You've watched a movie you'll forget in two weeks.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Excessive Detail&lt;/strong&gt;. Information is over-explained for universality - to suit beginners too. Even at 1.5-2x speed, I lacked patience and wanted to skip ahead. When a format irritates you, it's time to find alternatives.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;The Same Instructors Everywhere&lt;/strong&gt;. They'll teach you the entire JavaScript stack. Eventually, the same voices, mannerisms, and presentation styles become grating. Like your favorite song that you overplayed until you can't stand it anymore. No offense to the instructors - they're doing great work. This is about my perception evolving.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;The Boredom of Following Along&lt;/strong&gt;. I wanted to build my own ship, not copy someone else's blueprint. The value of courses evaporated - it became simpler to start a pet project and use documentation with AI to learn through practice.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Lack of Real Assessment&lt;/strong&gt;. Small automatic quizzes don't test actual skills. There's a desperate need for project assignments with subsequent review or mentoring.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Combined, you outgrow this format - it starts holding you back. The checkbox is ticked, but you haven't actually learned anything substantial.&lt;/p&gt;

&lt;p&gt;A perfect example: learning GraphQL. In video courses, everything looks logical and clear - schemas, resolvers, queries. You feel like you've mastered it. But in practice, the real fun begins: Apollo Client caching doesn't work as expected for your specific case, pagination combined with subscriptions breaks cache update logic, and error handling requires deep understanding of the framework's internals. What looks simple in a smooth tutorial flow can take hours of debugging and documentation diving in reality. This gap between "understood in theory" and "made it work in practice" is the format's key limitation.&lt;/p&gt;

&lt;p&gt;This format worked perfectly for about two years, then the need for change emerged. It's ideal when you're ready to move independently but aren't yet experienced - you don't have similar patterns in your head, and every detail is absorbed with interest. For experienced developers, the "follow along" format loses its value.&lt;/p&gt;

&lt;h2&gt;
  
  
  Stage 3: Documentation and Pet Projects - Independent Exploration
&lt;/h2&gt;

&lt;p&gt;If official documentation once seemed dry and non-sequential, failing to provide the big picture, experience flips everything upside down. With a mental model of the stack already formed, associative memory and intuition for common principles help you grasp new tools on the fly. You no longer need hand-holding and step-by-step instructions - documentation and solid Google-fu fill the gaps.&lt;/p&gt;

&lt;p&gt;It's fascinating to observe this evolution, when dry official documentation becomes the preferred learning method.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;No fluff&lt;/strong&gt; - you read exactly what you need, when you need it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Realistic learning&lt;/strong&gt; - you hit real errors, search for real solutions, and remember them because they hurt a little. You stumble, fall, get up, and that struggle makes the knowledge stick.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Transfer learning&lt;/strong&gt; - prior patterns help you grasp new tools faster, connecting the dots through intuition and experience.&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;“Reading documentation without building something is like reading a cookbook without cooking - you might understand the recipe, but you haven’t learned to cook.”&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Reading docs alone achieves nothing. The principle stays the same: learn by doing. Build your own ship (a learning pet project) and keep the docs open as your map. For example, this is how I kept my MERN stack skills fresh while working commercially on a different stack. When documentation is thin, bring in other tools selectively - the key is free flight: the ability to find, interpret, and apply information on your own.&lt;/p&gt;

&lt;p&gt;This format is harder for beginners - without an existing mental model, documentation can feel confusing and incomplete. But with experience, it’s faster and more “professional” than video tutorials.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The loop:&lt;/strong&gt; &lt;strong&gt;Project → Problem → Docs → Fix → Repeat&lt;/strong&gt;. That’s how you learn the way you actually work.&lt;/p&gt;

&lt;p&gt;This approach also addresses an industry paradox: job postings often demand &lt;em&gt;“2+ years of X”&lt;/em&gt; - but how do you get that if no one hires you without it? Self-study through documentation and pet projects isn’t identical to a job, but it’s closer than passively consuming tutorials. It proves you can solve problems in unfamiliar territory.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Rule of thumb:&lt;/strong&gt; Always start with a project. Let the project drive your reading list.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Stage 4: Courses with Assignments - Structure Plus Freedom
&lt;/h2&gt;

&lt;p&gt;Technologies constantly expand, new tools emerge. The Full-Stack role requires a broad knowledge base, but it's project-specific - you use far from the entire arsenal in any particular job, and logically, the rest fades. Eventually, endless throwaway pet projects also become tiresome and demotivating. You crave a new format.&lt;/p&gt;

&lt;p&gt;I recently discovered &lt;a href="https://fullstackopen.com/en/" rel="noopener noreferrer"&gt;Full Stack Open&lt;/a&gt; from the University of Helsinki, which perfectly suited both reviewing familiar technologies and learning new ones. It worked for me because:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Motivation matters.&lt;/strong&gt; You can earn official university credits. This requires actually submitting work. There's no direct feedback, but there's the feeling of it - repositories undergo manual review for credit allocation. And it's free.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Build it yourself.&lt;/strong&gt; Lots of assignments you must implement independently. You can extend them beyond the minimum. The course provides theory and direction, but you own the execution.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It's essentially the same as your own project with documentation, but under university patronage with a structured program. Sometimes it's pleasant to return to roots. As the proverb goes, &lt;em&gt;“Everything new is well-forgotten old.”&lt;/em&gt; This mixes different approaches with fresher air.&lt;/p&gt;

&lt;p&gt;Through FSO, I covered:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Backend:&lt;/strong&gt; Node.js, Express, Supertest, Node testing framework&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Frontend:&lt;/strong&gt; React, Redux Toolkit, React Query, Vitest, Playwright, Cypress&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Databases:&lt;/strong&gt; MongoDB, Mongoose, Sequelize, PostgreSQL&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;CI/CD:&lt;/strong&gt; GitHub Actions&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Containers:&lt;/strong&gt; Docker&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Other:&lt;/strong&gt; TypeScript, GraphQL&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;No, the brain can’t memorize every detail of all those technologies (I’ll write about cognitive limits another time). But you can learn to use them to solve real business problems.&lt;/p&gt;

&lt;h2&gt;
  
  
  Stage 5: Using AI in Learning - A Double-Edged Sword
&lt;/h2&gt;

&lt;p&gt;This is dangerous territory, and I haven't fully formed my boundaries yet, but some things deserve highlighting. AI can either accelerate your growth or completely stall your progress.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Upside:&lt;/strong&gt; AI is a 24/7 mentor that speeds up work, cuts hours of Googling and Stack Overflow searches, explains complex topics instantly, provides ready solutions.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Downside:&lt;/strong&gt; if you’re learning something &lt;em&gt;new&lt;/em&gt;, pasting AI-generated code directly into your project can rob you of the struggle that actually builds expertise. In learning mode, you &lt;em&gt;need&lt;/em&gt; the painful cycles: break → fix → refactor → repeat. That’s where understanding is forged.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Anti-pattern:&lt;/strong&gt; “Explain this code line by line and I’ll remember it.”&lt;br&gt;&lt;br&gt;
You won’t - if you didn’t fight for it.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Even if AI explains the code in detail, you’ll forget it because you didn’t live through the process. Experience matters far more than passive understanding. Copy-pasting ready solutions during learning is an anti-pattern: you haven’t internalized the mistakes and fixes, so you haven’t built the skill.&lt;/p&gt;

&lt;p&gt;If you’re already an experienced developer, leaning on AI isn’t as dangerous - you can read, adjust, and apply code consciously. But when learning new tools, you need to first become a specialist &lt;em&gt;without&lt;/em&gt; AI, and only then exploit it as leverage. Otherwise, you risk building an illusion of knowledge, only to discover you can’t solve even simple tasks without the crutch.&lt;/p&gt;

&lt;p&gt;One clarification: I’m not against AI in every context. I’m using it right now - not to generate my ideas, but to help polish my words into a readable article. That’s no different from hiring an editor. The thoughts are mine; the tool just helps me present them better. And that's OK, because I’m not aiming to become a professional writer or editor. But in my core craft - software development - the rules are different. That’s the contrast: if it’s your profession, you need to live through the work. If it’s not, outsourcing is just practical.&lt;/p&gt;

&lt;p&gt;This article isn’t meant to prescribe rules - I’m just sharing what I’ve observed. But after mentoring in an IT school for 4 years, I’ll risk one piece of advice for beginners: &lt;strong&gt;use AI extremely carefully, or better yet, don’t use it at all until you can confidently handle the technology without it.&lt;/strong&gt; The struggle is what makes the learning real.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Stayed True Across All Stages
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Active &amp;gt; passive.&lt;/strong&gt; Editors beat videos. Tickets beat lectures.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Theory + practice.&lt;/strong&gt; As the saying goes, "Theory without practice is dead, and practice without reflection is blind."&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Change the method, not the mission.&lt;/strong&gt; When a method stops working, switch it - don’t stop learning.&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;“Formats expire. Curiosity doesn’t.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Conclusion: To Learn Is to Adapt
&lt;/h2&gt;

&lt;p&gt;Looking back, I see a clear evolution: from structured learning with support, to full independence, and finally to a balanced mix of structure and freedom. Each stage was necessary and made perfect sense for its time.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;IT school&lt;/strong&gt; gave me the foundation and confidence to enter the profession.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Video courses&lt;/strong&gt; helped me quickly adopt new technologies in the early years.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Documentation with pet projects&lt;/strong&gt; taught me to solve problems in unfamiliar areas by extrapolating existing skills to unknown tools.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Practice-heavy courses&lt;/strong&gt; restored motivation and structure without taking away freedom.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;AI&lt;/strong&gt; became a powerful assistant - useful, but requiring careful guardrails.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The main discovery: &lt;strong&gt;your learning format must evolve with you&lt;/strong&gt;. But one principle never changes - stay an active learner, not a passive viewer.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What format works for you right now?&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Share your current stack (courses, routines, tools, rituals) in the comments. Have you noticed your learning style changing over the years? What triggered your transitions between different approaches? I’d love to compare experiences.&lt;/p&gt;

</description>
      <category>learning</category>
      <category>programming</category>
      <category>career</category>
    </item>
  </channel>
</rss>
