<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Lunatech's engineer blog</title>
	<atom:link href="https://blog.lunatech.com/feed/" rel="self" type="application/rss+xml" />
	<link>https://blog.lunatech.com</link>
	<description>Simplify your IT</description>
	<lastBuildDate>Sun, 24 Jan 2021 09:46:02 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	weekly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>Lunatech's blog engine</generator>

<image>
	<url>https://blog.lunatech.com/assets/images/logo-lunatech-france.png</url>
	<title>Lunatech's engineer blog</title>
	<link>https://blog.lunatech.com</link>
	<width>32</width>
	<height>32</height>
</image> 

 
	<item>
		<title>Change Detection Strategies in Angular: Zones and Signals</title>
		<link>https://blog.lunatech.com//posts/2025-11-05-change-detection-strategies-in-angular-zones-and-signals</link>
		
		<dc:creator><![CDATA[Jake Ortega]]></dc:creator>
        <pubDate>2025-11-05T00:00:00.000Z</pubDate>
         
             {
            <category><![CDATA[Intermediate]]></category>
                }
             {
            <category><![CDATA[change detection]]></category>
                }
             {
            <category><![CDATA[Zone.js]]></category>
                }
             {
            <category><![CDATA[OnPush]]></category>
                }
             {
            <category><![CDATA[signals (intro)]]></category>
                }
             {
            <category><![CDATA[en]]></category>
                }
             
        
		<guid isPermaLink="false">https://blog.lunatech.com//posts/2025-11-05-change-detection-strategies-in-angular-zones-and-signals</guid>

					<description>
                        <![CDATA[ Understand Angular’s change detection mechanism and how to optimize performance using the OnPush strategy. Learn how to use Signals for more granular reactivity. This article provides a practical mental model and shows how to apply it with Zone.js, OnPush, and Signals, along with a clear path toward building zoneless applications when you’re ready.]]></description>
                    <content:encoded><![CDATA[
                    <div id="preamble">
<div class="sectionbody">
<div class="paragraph">
<p>Understand Angular’s change detection mechanism and how to optimize performance using the OnPush strategy. Learn how to use Signals for more granular reactivity. This article provides a practical mental model and shows how to apply it with Zone.js, OnPush, and Signals, along with a clear path toward building zoneless applications when you’re ready.</p>
</div>
</div>
</div>
<div class="sect2">
<h3 id="_the_mental_model_how_angular_knows_to_update">The mental model: how Angular knows to update</h3>
<div class="paragraph">
<p>At a high level, Angular renders your component tree into a graph of views. A change detection pass checks template bindings and updates the DOM where something changed. Something has to tell Angular when to do that pass:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>With Zone.js (the default), Angular patches async APIs (Promises, setTimeout, DOM events, etc.) and schedules checks automatically after those tasks.</p>
</li>
<li>
<p>With signals, writes to a signal schedule the right components to re-render even without Zone.js.</p>
</li>
<li>
<p>With OnPush, Angular narrows when a component is checked: on input reference changes, events in that component, async pipe emissions, and signal writes.</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>Once you see what triggers checks, you can guide Angular to do less work and update only when it matters.</p>
</div>
</div>
<div class="sect2">
<h3 id="_working_with_zone_js_default">Working with Zone.js (default)</h3>
<div class="paragraph">
<p>Zone.js intercepts most async boundaries and calls into Angular to run change detection. It’s a safe default and reduces boilerplate, especially for teams migrating legacy code.</p>
</div>
<div class="paragraph">
<p>You can configure Zone.js coalescing to reduce redundant checks:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-typescript" data-lang="typescript">// app.config.ts
import { ApplicationConfig, provideZoneChangeDetection } from '@angular/core';
import { provideHttpClient } from '@angular/common/http';

export const appConfig: ApplicationConfig = {
  providers: [
    // Collapses multiple events/microtasks into fewer change detection cycles.
    provideZoneChangeDetection({
      eventCoalescing: true,
      runCoalescing: true,
    }),
    provideHttpClient(),
  ],
};</code></pre>
</div>
</div>
<div class="paragraph">
<p>For performance-sensitive work (e.g., animations or polling), run it outside Angular to avoid thrashing, and re-enter only when UI state actually changes.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-typescript" data-lang="typescript">import {
  Component,
  NgZone,
  ChangeDetectionStrategy,
  signal,
  inject,
  OnInit,
  OnDestroy
} from '@angular/core';

@Component({
  selector: 'cpu-heavy',
  standalone: true,
  template: `
    &lt;p&gt;Frames: {{ frames() }}&lt;/p&gt;
  `,
  changeDetection: ChangeDetectionStrategy.OnPush,
})
export class CpuHeavyComponent implements OnInit, OnDestroy {
  private zone = inject(NgZone);

  // Signal handles reactivity; no CDR needed
  private _frames = signal(0);
  frames = this._frames.asReadonly();

  private intervalId?: ReturnType&lt;typeof setInterval&gt;;

  ngOnInit() {
    this.zone.runOutsideAngular(() =&gt; {
      let n = 0;
      this.intervalId = setInterval(() =&gt; {
        // Update signal outside Angular zone
        // Signals batch updates automatically
        this._frames.set(++n);

        if (n &gt; 3000) {
          clearInterval(this.intervalId);
        }
      }, 16);
    });
  }

  ngOnDestroy() {
    if (this.intervalId) {
      clearInterval(this.intervalId);
    }
  }
}</code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="_embracing_onpush_for_predictable_performance">Embracing OnPush for predictable performance</h3>
<div class="paragraph">
<p>OnPush reduces unnecessary checks and nudges you toward immutable data and explicit updates. Angular will check an OnPush component when:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>An Input reference changes (immutability shines here).</p>
</li>
<li>
<p>The component fires an event or an async pipe emits.</p>
</li>
<li>
<p>A bound signal writes (signals integrate with the scheduler).</p>
</li>
<li>
<p>You explicitly call markForCheck or detectChanges.</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>Use immutable updates for inputs and track nodes for stable lists.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-typescript" data-lang="typescript">import { Component, ChangeDetectionStrategy, input } from '@angular/core';

type User = { id: number; name: string };

@Component({
  selector: 'user-list',
  standalone: true,
  template: `
    &lt;ul&gt;
      @for (u of users(); track u.id) {
        &lt;li&gt;{{ u.name }}&lt;/li&gt;
      }
    &lt;/ul&gt;
  `,
  changeDetection: ChangeDetectionStrategy.OnPush,
})
export class UserListComponent {
  // Signal-based input (works great with OnPush)
  users = input&lt;ReadonlyArray&lt;User&gt;&gt;([]);
}</code></pre>
</div>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-typescript" data-lang="typescript">// parent.component.ts
import { Component, ChangeDetectionStrategy, signal } from '@angular/core';
import { UserListComponent } from './user-list.component';

type User = { id: number; name: string };

@Component({
  selector: 'parent',
  standalone: true,
  imports: [UserListComponent],
  template: `
    &lt;button (click)="add()"&gt;Add&lt;/button&gt;
    &lt;button (click)="mutate()"&gt;Mutate (bad)&lt;/button&gt;

    &lt;user-list [users]="users()"&gt;&lt;/user-list&gt;
  `,
  changeDetection: ChangeDetectionStrategy.OnPush,
})
export class ParentComponent {
  private _users = signal&lt;ReadonlyArray&lt;User&gt;&gt;([
    { id: 1, name: 'Maya' },
    { id: 2, name: 'Dee' },
  ]);
  users = this._users.asReadonly();

  // Correct: immutable update changes the reference and triggers OnPush
  add() {
    const currentIds = this.users().map(u =&gt; u.id);
    const nextId = currentIds.length &gt; 0 ? Math.max(...currentIds) + 1 : 1;
    this._users.update(arr =&gt; [...arr, { id: nextId, name: 'New User' }]);
  }

  // Bad: mutates in place; OnPush children won't see a different reference
  mutate() {
    // as any to showcase the pitfall (avoid in real code)
    (this.users() as any)[0].name = 'Mutated';
    // The UI may not update; prefer immutable patterns.
  }
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>If you&#8217;re not using signals and you must update UI from a callback that Angular doesn&#8217;t know about, call markForCheck.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-typescript" data-lang="typescript">import { Component, ChangeDetectionStrategy, ChangeDetectorRef, OnInit } from '@angular/core';

@Component({
  selector: 'ws-status',
  standalone: true,
  template: `Status: {{ status }}`,
  changeDetection: ChangeDetectionStrategy.OnPush,
})
export class WebSocketStatusComponent implements OnInit {
  status = 'disconnected';
  constructor(private cdr: ChangeDetectorRef) {}

  ngOnInit() {
    const ws = new WebSocket('wss://example.org');
    ws.onopen = () =&gt; { this.status = 'connected'; this.cdr.markForCheck(); };
    ws.onclose = () =&gt; { this.status = 'disconnected'; this.cdr.markForCheck(); };
  }
}</code></pre>
</div>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-typescript" data-lang="typescript">import { Component, ChangeDetectionStrategy, ChangeDetectorRef } from '@angular/core';

@Component({
  selector: 'ws-status',
  standalone: true,
  template: `Status: {{ status }}`,
  changeDetection: ChangeDetectionStrategy.OnPush,
})
export class WebSocketStatusComponent {
  status = 'disconnected';
  constructor(private cdr: ChangeDetectorRef) {}

  ngOnInit() {
    const ws = new WebSocket('wss://example.org');
    ws.onopen = () =&gt; { this.status = 'connected'; this.cdr.markForCheck(); };
    ws.onclose = () =&gt; { this.status = 'disconnected'; this.cdr.markForCheck(); };
  }
}</code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="_signals_intro_finegrained_reactivity_without_heavy_lifting">Signals (intro): fine‑grained reactivity without heavy lifting</h3>
<div class="paragraph">
<p>Signals give you a declarative, dependency-tracked model for state. Reading a signal in a template links it to the view; writing to that signal schedules the right view to update. This makes change detection more targeted and pairs naturally with OnPush or even zoneless.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-typescript" data-lang="typescript">import { Component, ChangeDetectionStrategy, signal, computed, effect } from '@angular/core';

type Todo = { id: number; title: string; done: boolean };

@Component({
  selector: 'todo-panel',
  standalone: true,
  template: `
    &lt;input placeholder="Filter..." [value]="filter()" (input)="filter.set(($event.target as HTMLInputElement).value)" /&gt;

    &lt;p&gt;Completed: {{ completedCount() }} / {{ todos().length }}&lt;/p&gt;

    &lt;ul&gt;
      @for (t of filteredTodos(); track t.id) {
        &lt;li&gt;
          &lt;label&gt;
            &lt;input type="checkbox" [checked]="t.done" (change)="toggle(t.id)" /&gt;
            {{ t.title }}
          &lt;/label&gt;
        &lt;/li&gt;
      }
    &lt;/ul&gt;
  `,
  changeDetection: ChangeDetectionStrategy.OnPush,
})
export class TodoPanelComponent {
  private _todos = signal&lt;Todo[]&gt;([
    { id: 1, title: 'Ship dashboard', done: false },
    { id: 2, title: 'Write docs', done: true },
  ]);
  todos = this._todos.asReadonly();

  filter = signal('');
  filteredTodos = computed(() =&gt; {
    const q = this.filter().toLowerCase();
    return this.todos().filter(t =&gt; t.title.toLowerCase().includes(q));
  });
  completedCount = computed(() =&gt; this.todos().filter(t =&gt; t.done).length);

  toggle(id: number) {
    this._todos.update(ts =&gt; ts.map(t =&gt; (t.id === id ? { ...t, done: !t.done } : t)));
  }

  // Optional: side effects
  log = effect(() =&gt; {
    console.debug('Todos changed:', this.todos());
  });
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>Interop with RxJS is straightforward; toSignal turns an Observable into a signal that drives OnPush views.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-typescript" data-lang="typescript">import { toSignal } from '@angular/core/rxjs-interop';
import { Observable } from 'rxjs';

@Component({ /* ... */ })
export class ClockComponent {
  now = toSignal(
    // Emits a new Date every second
    new Observable&lt;Date&gt;(sub =&gt; {
      const id = setInterval(() =&gt; sub.next(new Date()), 1000);
      return () =&gt; clearInterval(id);
    }),
    { initialValue: new Date() }
  );
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>Because writing to signals schedules view updates, you often don’t need ChangeDetectorRef calls. The result is simpler, more predictable change detection.</p>
</div>
</div>
<div class="sect2">
<h3 id="_zoneless_change_detection_when_youre_ready_to_drop_zone_js">Zoneless change detection: when you&#8217;re ready to drop Zone.js</h3>
<div class="paragraph">
<p>Zoneless mode lets Angular skip patching browser APIs (no Zone.js) and rely purely on explicit reactive triggers (signals, template events, async pipe, router). By Angular 20, zoneless is mature enough for production in well-structured, signal‑driven apps.</p>
</div>
<div class="paragraph">
<p>Use the stable provider if it exists; otherwise keep using the experimental one until your project confirms the upgrade path.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-typescript" data-lang="typescript">// app.config.ts
import { ApplicationConfig, provideHttpClient } from '@angular/common/http';
import {
  // Verify which one exists in your installed version:
  // If Angular 20 exposes `provideZonelessChangeDetection`, prefer it.
  provideZonelessChangeDetection,               // &lt;-- Confirm availability
  provideExperimentalZonelessChangeDetection,   // &lt;-- Fallback if stable not present
} from '@angular/core';

export const appConfig: ApplicationConfig = {
  providers: [
    // Use ONE of the following:
    // provideZonelessChangeDetection(),
    provideExperimentalZonelessChangeDetection(), // ← Remove when stable provider confirmed
    provideHttpClient(),
  ],
};</code></pre>
</div>
</div>
<div class="paragraph">
<p>With zoneless, Angular still updates views when:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>Template events fire (click, input, etc.).</p>
</li>
<li>
<p>A signal is written (set/update).</p>
</li>
<li>
<p>AsyncPipe emits (it marks its view manually).</p>
</li>
<li>
<p>Router navigation completes.</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>Other async sources (WebSocket, timers, SDK callbacks): funnel them through signals (or Observables bound via async pipe / toSignal). Avoid manual ChangeDetectorRef unless integrating with legacy patterns.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-typescript" data-lang="typescript">import { Component, ChangeDetectionStrategy, signal } from '@angular/core';
import { toSignal } from '@angular/core/rxjs-interop';
import { interval, map, startWith } from 'rxjs';

@Component({
  selector: 'zoneless-demo',
  standalone: true,
  template: `
    &lt;p&gt;Server time: {{ time() }}&lt;/p&gt;
    &lt;p&gt;Clicks: {{ clicks() }}&lt;/p&gt;
    &lt;button (click)="inc()"&gt;Click me&lt;/button&gt;
  `,
  changeDetection: ChangeDetectionStrategy.OnPush,
})
export class ZonelessDemoComponent {
  time = toSignal(
    interval(1000).pipe(
      map(() =&gt; new Date().toLocaleTimeString()),
      startWith(new Date().toLocaleTimeString()),
    ),
    { initialValue: new Date().toLocaleTimeString() },
  );

  private _clicks = signal(0);
  clicks = this._clicks.asReadonly();

  inc() {
    this._clicks.update(n =&gt; n + 1);
  }
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>If you interact with non-Angular callbacks (e.g., third‑party SDKs), prefer to set signals inside the callback. That write will schedule the needed view updates.</p>
</div>
</div>
<div class="sect2">
<h3 id="_practical_checklist">Practical checklist</h3>
<div class="ulist">
<ul>
<li>
<p>Prefer OnPush for all app components; combine with immutable data.</p>
</li>
<li>
<p>Use signal-based inputs (input()) in leaf components for ergonomic, fine-grained updates.</p>
</li>
<li>
<p>Store local UI state as signals; use computed for derivations and effect for side effects.</p>
</li>
<li>
<p>In Zone.js apps, isolate heavy loops with runOutsideAngular and re-enter only on state writes.</p>
</li>
<li>
<p>In zoneless apps, ensure all UI-affecting async work flows through signals or async pipe.</p>
</li>
<li>
<p>Track list items by a stable key to avoid re-render churn.</p>
</li>
<li>
<p>Use provideZoneChangeDetection with coalescing in legacy/mixed environments; move toward provideExperimentalZonelessChangeDetection when your reactive pathways are solid.</p>
</li>
</ul>
</div>
</div>
<div class="sect2">
<h3 id="_troubleshooting_gotchas">Troubleshooting gotchas</h3>
<div class="ulist">
<ul>
<li>
<p>“My OnPush child didn’t update.” Ensure the Input reference changes (immutable update) or the child reads a signal that you wrote to.</p>
</li>
<li>
<p>“Zoneless didn’t repaint after a callback.” Convert that callback’s data to a signal or trigger an async pipe emission; avoid manual detectChanges unless you know the implications.</p>
</li>
<li>
<p>“Perf regressions after refactor.” Check for unintended synchronous effects that write many signals in a loop; batch updates if needed, or compose a single state write.</p>
</li>
</ul>
</div>
</div>
<div class="sect2">
<h3 id="_conclusion">Conclusion</h3>
<div class="paragraph">
<p>Change detection in Angular is powerful because you can choose the right tool for the job. Zone.js gives you simplicity, OnPush gives you predictability and performance, and signals give you precise, maintainable reactivity. Together, they help you ship fast UIs without guesswork, and you can progressively adopt a zoneless model when your state is signal-driven.</p>
</div>
</div>
<div class="sect2">
<h3 id="_next_steps">Next Steps</h3>
<div class="ulist">
<ul>
<li>
<p>Audit your components: enable OnPush and fix any mutable input flows.</p>
</li>
<li>
<p>Introduce signals for local state and derived values; replace ad‑hoc ChangeDetectorRef calls.</p>
</li>
<li>
<p>Wrap recurring async sources (timers, sockets) with toSignal or async pipe.</p>
</li>
<li>
<p>Experiment with provideExperimentalZonelessChangeDetection in a feature slice to validate your reactive pathways.</p>
</li>
<li>
<p>Read the Angular guides on signals and zoneless change detection to deepen your understanding.</p>
</li>
</ul>
</div>
</div>
<]]></content:encoded>
					
		
		
			</item>
         
	<item>
		<title>Getting Started with Angular 20 CLI and Standalone Components</title>
		<link>https://blog.lunatech.com//posts/2025-10-27-getting-started-with-angular-20-cli-and-standalone-components</link>
		
		<dc:creator><![CDATA[Jake Ortega]]></dc:creator>
        <pubDate>2025-10-27T00:00:00.000Z</pubDate>
         
             {
            <category><![CDATA[Beginner]]></category>
                }
             {
            <category><![CDATA[Angular CLI]]></category>
                }
             {
            <category><![CDATA[standalone components]]></category>
                }
             {
            <category><![CDATA[en]]></category>
                }
             
        
		<guid isPermaLink="false">https://blog.lunatech.com//posts/2025-10-27-getting-started-with-angular-20-cli-and-standalone-components</guid>

					<description>
                        <![CDATA[ Learn how to initialize and structure a new Angular 20 project using the Angular CLI. Understand standalone components and the simplified bootstrapping process. This guide focuses on a clean project setup, modern routing, and practical patterns you can reuse in real projects.]]></description>
                    <content:encoded><![CDATA[
                    <div id="preamble">
<div class="sectionbody">
<div class="paragraph">
<p>Learn how to initialize and structure a new Angular 20 project using the Angular CLI. Understand standalone components and the simplified bootstrapping process. This guide focuses on a clean project setup, modern routing, and practical patterns you can reuse in real projects.</p>
</div>
</div>
</div>
<div class="sect2">
<h3 id="_prerequisites">Prerequisites</h3>
<div class="ulist">
<ul>
<li>
<p>Node.js 24+ (LTS recommended) and npm or pnpm</p>
</li>
<li>
<p>Angular CLI 20 installed globally: npm i -g @angular/cli@20</p>
</li>
<li>
<p>Familiarity with TypeScript and Angular fundamentals</p>
</li>
</ul>
</div>
</div>
<div class="sect2">
<h3 id="_create_a_new_project_with_the_angular_cli">Create a new project with the Angular CLI</h3>
<div class="paragraph">
<p>The Angular CLI scaffolds a production-grade baseline with sensible defaults. Standalone components are the default in Angular 20, which means no NgModules are required for most apps.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-shell" data-lang="shell">// Terminal
// Create a new app with routing and SCSS. Use --ssr to scaffold server-side rendering.
ng new lt-dashboard --routing --style=scss
cd lt-dashboard
ng serve</code></pre>
</div>
</div>
<div class="paragraph">
<p>Open <a href="http://localhost:4200" class="bare">http://localhost:4200</a> and confirm the app runs. The CLI gives you fast dev server reloads, TypeScript checks, and a ready-to-extend project.</p>
</div>
</div>
<div class="sect2">
<h3 id="_project_structure_that_scales">Project structure that scales</h3>
<div class="paragraph">
<p>A small, predictable layout keeps cognitive load low as features grow.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-typescript" data-lang="typescript">// Suggested structure (simplified)
src/
  main.ts
  index.html
  styles.scss
  environments/
    environment.ts
    environment.prod.ts
  app/
    app.component.ts
    app.routes.ts
    features/
      home/
        home.component.ts
      projects/
        projects.component.ts</code></pre>
</div>
</div>
<div class="ulist">
<ul>
<li>
<p><strong>app.routes.ts</strong> holds your route config.</p>
</li>
<li>
<p>Each feature gets its own folder with a standalone component.</p>
</li>
<li>
<p>environments holds build-time configuration.</p>
</li>
</ul>
</div>
</div>
<div class="sect2">
<h3 id="_simplified_bootstrapping_with_bootstrapapplication">Simplified bootstrapping with bootstrapApplication</h3>
<div class="paragraph">
<p>Standalone components and functional providers eliminate boilerplate. The entry point is lean and explicit.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-typescript" data-lang="typescript">// src/main.ts
import { bootstrapApplication } from '@angular/platform-browser';
import { provideRouter, withComponentInputBinding } from '@angular/router';
import { provideHttpClient, HttpInterceptorFn, withInterceptors } from '@angular/common/http';
import { provideAnimations } from '@angular/platform-browser/animations';
import { AppComponent } from './app/app.component';
import { routes } from './app/app.routes';

// Example functional interceptor (adds a version header)
const versionHeaderInterceptor: HttpInterceptorFn = (req, next) =&gt;
  next(req.clone({ setHeaders: { 'X-App-Version': '1.0.0' } }));

bootstrapApplication(AppComponent, {
  providers: [
    provideRouter(routes, withComponentInputBinding()),
    provideHttpClient(withInterceptors([versionHeaderInterceptor])),
    provideAnimations(),
    // If you generated the project with --ssr, enable hydration:
    // provideClientHydration(),
  ],
}).catch(err =&gt; console.error(err));</code></pre>
</div>
</div>
<div class="ulist">
<ul>
<li>
<p><strong>provideRouter</strong> wires your routing without a root NgModule.</p>
</li>
<li>
<p>provideHttpClient configures HttpClient with tree-shakable features like withInterceptors.</p>
</li>
<li>
<p>provideAnimations enables Angular animations globally.</p>
</li>
<li>
<p>withComponentInputBinding lets you bind route params/data directly to component inputs.</p>
</li>
</ul>
</div>
</div>
<div class="sect2">
<h3 id="_routing_with_lazy_standalone_components">Routing with lazy standalone components</h3>
<div class="paragraph">
<p>Define routes in a single place and lazy-load components with loadComponent.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-typescript" data-lang="typescript">// src/app/app.routes.ts
import { Routes } from '@angular/router';

export const routes: Routes = [
  {
    path: '',
    loadComponent: () =&gt;
      import('./features/home/home.component').then(m =&gt; m.HomeComponent),
    title: 'Home',
  },
  {
    path: 'projects',
    loadComponent: () =&gt;
      import('./features/projects/projects.component').then(m =&gt; m.ProjectsComponent),
    title: 'Projects',
  },
  { path: '**', redirectTo: '' },
];</code></pre>
</div>
</div>
<div class="paragraph">
<p>This setup is fast to read and easy to evolve. Each path points directly at a standalone component without an intermediate NgModule.</p>
</div>
</div>
<div class="sect2">
<h3 id="_a_minimal_root_component">A minimal root component</h3>
<div class="paragraph">
<p>Keep your root component focused on layout and navigation.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-typescript" data-lang="typescript">// src/app/app.component.ts
import { Component } from '@angular/core';
import { RouterLink, RouterLinkActive, RouterOutlet } from '@angular/router';

@Component({
  selector: 'app-root',
  standalone: true,
  imports: [RouterOutlet, RouterLink, RouterLinkActive],
  styles: [`
    nav { display: flex; gap: 1rem; padding: 1rem; border-bottom: 1px solid #eee; }
    a.active { font-weight: 600; text-decoration: underline; }
    main { padding: 1rem; }
  `],
  template: `
    &lt;nav&gt;
      &lt;a routerLink="/" routerLinkActive="active" [routerLinkActiveOptions]="{ exact: true }"&gt;Home&lt;/a&gt;
      &lt;a routerLink="/projects" routerLinkActive="active"&gt;Projects&lt;/a&gt;
    &lt;/nav&gt;
    &lt;main&gt;
      &lt;router-outlet /&gt;
    &lt;/main&gt;
  `,
})
export class AppComponent {}</code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="_build_a_real_feature_home_with_forms_and_new_control_flow">Build a real feature: Home with forms and new control flow</h3>
<div class="paragraph">
<p>Use reactive forms and the modern control flow syntax (@if, @for) to keep templates expressive and predictable.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-typescript" data-lang="typescript">// src/app/features/home/home.component.ts
import { Component, signal } from '@angular/core';
import { FormBuilder, ReactiveFormsModule } from '@angular/forms';

type Project = { id: number; name: string };

@Component({
  imports: [ReactiveFormsModule],
  styles: [`
    form { display: flex; gap: 0.5rem; margin: 1rem 0; }
    input { min-width: 240px; }
    ul { padding-left: 1.25rem; }
  `],
  template: `
    &lt;h2&gt;Welcome&lt;/h2&gt;

    &lt;form [formGroup]="searchForm" (ngSubmit)="onSearch()"&gt;
      &lt;input formControlName="q" type="text" placeholder="Search projects" /&gt;
      &lt;button type="submit"&gt;Search&lt;/button&gt;
      &lt;button type="button" (click)="reset()"&gt;Reset&lt;/button&gt;
    &lt;/form&gt;

    @if (results().length === 0) {
      &lt;p&gt;No results found.&lt;/p&gt;
    } @else {
      &lt;ul&gt;
        @for (p of results(); track p.id) {
          &lt;li&gt;{{ p.name }}&lt;/li&gt;
        }
      &lt;/ul&gt;
    }
  `,
})
export class HomeComponent {
  private readonly allProjects: Project[] = [
    { id: 1, name: 'Roadmap' },
    { id: 2, name: 'UI Kit' },
    { id: 3, name: 'Infra' },
  ];

  results = signal&lt;Project[]&gt;(this.allProjects);

  constructor(private fb: FormBuilder) {}

  searchForm = this.fb.nonNullable.group({ q: '' });

  onSearch(): void {
    const q = this.searchForm.value.q?.toLowerCase() ?? '';
    this.results.set(
      this.allProjects.filter(p =&gt; p.name.toLowerCase().includes(q))
    );
  }

  reset(): void {
    this.searchForm.reset({ q: '' });
    this.results.set(this.allProjects);
  }
}</code></pre>
</div>
</div>
<div class="ulist">
<ul>
<li>
<p>signal gives you ergonomic local state without services when you don’t need them.</p>
</li>
<li>
<p>The new control flow removes structural directive noise while remaining explicit.</p>
</li>
</ul>
</div>
</div>
<div class="sect2">
<h3 id="_a_lazy_projects_page">A lazy projects page</h3>
<div class="paragraph">
<p>Keep feature components focused and stateless by default.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-typescript" data-lang="typescript">// src/app/features/projects/projects.component.ts
import { Component } from '@angular/core';

@Component({
  template: `
    &lt;h2&gt;Projects&lt;/h2&gt;
    &lt;p&gt;This is a lazy-loaded page. Add tables, filters, or charts here.&lt;/p&gt;
  `,
})
export class ProjectsComponent {}</code></pre>
</div>
</div>
<div class="paragraph">
<p>The route configuration we defined earlier will load this component on demand.</p>
</div>
</div>
<div class="sect2">
<h3 id="_http_setup_with_functional_interceptors">HTTP setup with functional interceptors</h3>
<div class="paragraph">
<p>You already provided HttpClient in main.ts. Add domain-specific concerns via functional interceptors as your app grows (auth tokens, correlation IDs, error normalization). They compose with withInterceptors and stay tree-shakable.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-typescript" data-lang="typescript">// Example: src/app/core/auth.interceptor.ts (optional)
import { HttpInterceptorFn } from '@angular/common/http';

export const authInterceptor: HttpInterceptorFn = (req, next) =&gt; {
  const token = localStorage.getItem('token');
  return next(token ? req.clone({ setHeaders: { Authorization: `Bearer ${token}` } }) : req);
};

// Then in main.ts:
// provideHttpClient(withInterceptors([authInterceptor, versionHeaderInterceptor]))</code></pre>
</div>
</div>
<div class="paragraph">
<p>Keep cross-cutting code small, testable, and colocated in core/.</p>
</div>
</div>
<div class="sect2">
<h3 id="_environment_driven_configuration">Environment-driven configuration</h3>
<div class="paragraph">
<p>Use build-time environments for API base URLs and toggles. The CLI swaps files based on configuration.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-typescript" data-lang="typescript">// src/environments/environment.ts
export const environment = {
  production: false,
  apiUrl: 'http://localhost:3000/api',
};

// src/environments/environment.prod.ts
export const environment = {
  production: true,
  apiUrl: 'https://api.example.com',
};</code></pre>
</div>
</div>
<div class="paragraph">
<p>Access where needed:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-typescript" data-lang="typescript">// Anywhere in app code
import { environment } from '../environments/environment';
// http.get(`${environment.apiUrl}/projects`)</code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="_cli_commands_youll_use_daily">CLI commands you’ll use daily</h3>
<div class="ulist">
<ul>
<li>
<p>Generate features: ng g component app/features/activity</p>
</li>
<li>
<p>Add utilities: ng g interceptor core/logging</p>
</li>
<li>
<p>Run locally: ng serve</p>
</li>
<li>
<p>Build for production: ng build --configuration production</p>
</li>
<li>
<p>Run unit tests: ng test</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>The Angular CLI keeps project setup consistent while remaining flexible.</p>
</div>
</div>
<div class="sect2">
<h3 id="_optional_server_side_rendering_ssr">Optional: Server-side rendering (SSR)</h3>
<div class="paragraph">
<p>If you create your project with --ssr, the CLI scaffolds an SSR server and hydration for you. In main.ts, include provideClientHydration() so the browser picks up the server-rendered DOM without re-rendering. SSR improves Time to First Byte (TTFB), SEO, and perceived performance for content-heavy routes.</p>
</div>
</div>
<div class="sect2">
<h3 id="_why_this_structure_works">Why this structure works</h3>
<div class="ulist">
<ul>
<li>
<p>Standalone components reduce indirection and speed up onboarding.</p>
</li>
<li>
<p>A single routes file gives you a map of the app at a glance.</p>
</li>
<li>
<p>Providers in main.ts make cross-cutting behavior explicit.</p>
</li>
<li>
<p>Feature-first folders keep implementation details close to their templates and styles.</p>
</li>
</ul>
</div>
</div>
<div class="sect2">
<h3 id="_troubleshooting_and_tips">Troubleshooting and tips</h3>
<div class="ulist">
<ul>
<li>
<p>Type errors on control flow (@if/@for): ensure your component template uses the new Angular control flow (Angular 17+). No extra imports are needed.</p>
</li>
<li>
<p>RouterLinkActive not working on root: pass [routerLinkActiveOptions]="{ exact: true }" for the root link.</p>
</li>
<li>
<p>Interceptor order: interceptors run in the order provided for requests, and in reverse for responses. Put auth/correlation early; place global error handling last to see the final response state.</p>
</li>
</ul>
</div>
</div>
<div class="sect2">
<h3 id="_conclusion">Conclusion</h3>
<div class="paragraph">
<p>Angular 20 cuts the ceremony: standalone components by default, functional providers, and minimal bootstrapping. Organize by feature, keep routes clear, and scale without the bloat. The CLI does the grunt work, you build features.</p>
</div>
</div>
<div class="sect2">
<h3 id="_next_steps">Next Steps</h3>
<div class="ulist">
<ul>
<li>
<p>Add a core/ directory for cross-cutting concerns (interceptors, guards, tokens).</p>
</li>
<li>
<p>Introduce a shared/ library for reusable UI primitives.</p>
</li>
<li>
<p>Wire HttpClient to a real backend and centralize API calls behind a data-access service.</p>
</li>
<li>
<p>Enable SSR (--ssr) and hydration for content-rich pages.</p>
</li>
<li>
<p>Adopt signals in more places thoughtfully: state local to a component is a good fit; shared, cross-route state still belongs in services.</p>
</li>
</ul>
</div>
</div>
<]]></content:encoded>
					
		
		
			</item>
         
	<item>
		<title>Routing in Angular 20: Basics to Navigation Guards</title>
		<link>https://blog.lunatech.com//posts/2025-10-22-routing-in-angular-20-basics-to-navigation-guards</link>
		
		<dc:creator><![CDATA[Jake Ortega]]></dc:creator>
        <pubDate>2025-10-22T00:00:00.000Z</pubDate>
         
             {
            <category><![CDATA[Beginner]]></category>
                }
             {
            <category><![CDATA[angular router]]></category>
                }
             {
            <category><![CDATA[navigation]]></category>
                }
             {
            <category><![CDATA[route guards]]></category>
                }
             {
            <category><![CDATA[async redirects]]></category>
                }
             {
            <category><![CDATA[en]]></category>
                }
             
        
		<guid isPermaLink="false">https://blog.lunatech.com//posts/2025-10-22-routing-in-angular-20-basics-to-navigation-guards</guid>

					<description>
                        <![CDATA[ Master client-side routing with Angular’s Router. Learn route configuration, navigation, guards, and Angular 20’s asynchronous redirect improvements.]]></description>
                    <content:encoded><![CDATA[
                    <div id="preamble">
<div class="sectionbody">
<div class="paragraph">
<p>Master client-side routing with Angular’s Router. Learn route configuration, navigation, guards, and Angular 20’s asynchronous redirect improvements.</p>
</div>
</div>
</div>
<div class="sect2">
<h3 id="_why_the_router_still_matters">Why the Router still matters</h3>
<div class="paragraph">
<p>Routing is the backbone of user flow. It defines how screens load, what data they need, and how access is enforced. A reliable setup pays off when your app scales and your team grows. In Angular 20, the Angular Router keeps moving in the right direction: clearer configuration, better async flows, and ergonomics that prioritize maintainability.</p>
</div>
<div class="paragraph">
<p>This guide walks through a practical baseline: route configuration, links, programmatic navigation, route guards, and async redirects, all with standalone components and functional APIs.</p>
</div>
</div>
<div class="sect2">
<h3 id="_a_minimal_modern_router_setup">A minimal, modern router setup</h3>
<div class="paragraph">
<p>Use standalone APIs and <strong>provideRouter</strong> for a clean bootstrap.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-typescript" data-lang="typescript">// main.ts
import { bootstrapApplication } from '@angular/platform-browser';
import { provideRouter, withPreloading, PreloadAllModules } from '@angular/router';
import { AppComponent } from './app/app.component';
import { routes } from './app/app.routes';

bootstrapApplication(AppComponent, {
  providers: [
    provideRouter(
      routes,
      withPreloading(PreloadAllModules),
    ),
  ],
});</code></pre>
</div>
</div>
<div class="paragraph">
<p>Define your routes in a dedicated file. Prefer lazy-loading to keep initial bundles lean.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-typescript" data-lang="typescript">// app/app.routes.ts
import { Routes } from '@angular/router';
import { authCanActivate, authCanMatch, unsavedCanDeactivate } from './auth/guards';

export const routes: Routes = [
  { path: '', redirectTo: 'home', pathMatch: 'full' },

  {
    path: 'home',
    title: 'Home',
    loadComponent: () =&gt; import('./features/home/home.component').then(m =&gt; m.HomeComponent),
  },
  {
    path: 'dashboard',
    title: 'Dashboard',
    canActivate: [authCanActivate],
    loadComponent: () =&gt; import('./features/dashboard/dashboard.component').then(m =&gt; m.DashboardComponent),
  },
  {
    path: 'projects',
    canMatch: [authCanMatch],
    loadChildren: () =&gt; import('./features/projects/projects.routes').then(m =&gt; m.PROJECTS_ROUTES),
  },
  {
    path: 'settings',
    title: 'Settings',
    canDeactivate: [unsavedCanDeactivate],
    loadComponent: () =&gt; import('./features/settings/settings.component').then(m =&gt; m.SettingsComponent),
  },
  {
    path: 'login',
    title: 'Sign in',
    loadComponent: () =&gt; import('./features/auth/login.component').then(m =&gt; m.LoginComponent),
  },
  {
    path: '**',
    title: 'Not Found',
    loadComponent: () =&gt; import('./shared/not-found/not-found.component').then(m =&gt; m.NotFoundComponent),
  },
];</code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="_the_application_shell_links_and_outlet">The application shell: links and outlet</h3>
<div class="paragraph">
<p>Make navigation obvious and accessible. Use RouterLink and RouterLinkActive for feedback.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-html" data-lang="html">&lt;!-- app/app.component.html --&gt;
&lt;header class="app-header"&gt;
  &lt;nav&gt;
    &lt;a routerLink="/home" routerLinkActive="active" [routerLinkActiveOptions]="{ exact: true }"&gt;Home&lt;/a&gt;
    &lt;a routerLink="/dashboard" routerLinkActive="active"&gt;Dashboard&lt;/a&gt;
    &lt;a routerLink="/projects" routerLinkActive="active"&gt;Projects&lt;/a&gt;
    &lt;a routerLink="/settings" routerLinkActive="active"&gt;Settings&lt;/a&gt;
  &lt;/nav&gt;
&lt;/header&gt;

&lt;main&gt;
  &lt;router-outlet&gt;&lt;/router-outlet&gt;
&lt;/main&gt;</code></pre>
</div>
</div>
<div class="paragraph">
<p>RouterLink keeps your templates declarative; RouterOutlet hosts the matched view. For accessibility and UX, the active class communicates where the user is during navigation.</p>
</div>
</div>
<div class="sect2">
<h3 id="_a_realistic_feature_route_with_params_and_lazy_loading">A realistic feature route with params and lazy-loading</h3>
<div class="paragraph">
<p>For features like Projects, lazy load the route definition and child screens.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-typescript" data-lang="typescript">// features/projects/projects.routes.ts
import { Routes } from '@angular/router';

export const PROJECTS_ROUTES: Routes = [
  {
    path: '',
    title: 'Projects',
    loadComponent: () =&gt; import('./list/projects-list.component').then(m =&gt; m.ProjectsListComponent),
  },
  {
    path: ':id',
    title: 'Project Details',
    loadComponent: () =&gt; import('./details/project-details.component').then(m =&gt; m.ProjectDetailsComponent),
  },
];</code></pre>
</div>
</div>
<div class="paragraph">
<p>In a details component, read route params. Use clean, testable patterns.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-typescript" data-lang="typescript">// features/projects/details/project-details.component.ts
import { Component, computed, inject } from '@angular/core';
import { ActivatedRoute, Router } from '@angular/router';
import { toSignal } from '@angular/core/rxjs-interop';
import { ProjectService } from '../data/project.service';

@Component({
  standalone: true,
  selector: 'app-project-details',
  template: `
    @if (project(); as data) {
      &lt;h2&gt;{{ data.name }}&lt;/h2&gt;
      &lt;button (click)="goBack()"&gt;Back&lt;/button&gt;
    } @else {
      &lt;p&gt;Project not found.&lt;/p&gt;
    }
  `,
})
export class ProjectDetailsComponent {
  private route = inject(ActivatedRoute);
  private router = inject(Router);
  private service = inject(ProjectService);

  private paramMap = toSignal(this.route.paramMap, { initialValue: this.route.snapshot.paramMap });
  id = computed(() =&gt; this.paramMap()?.get('id') ?? null);

  project = toSignal(this.service.getProjectStream(this.route.paramMap), { initialValue: null });

  goBack() {
    this.router.navigate(['../'], { relativeTo: this.route });
  }
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>Notes:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>Use toSignal when a component benefits from reactive values in the template.</p>
</li>
<li>
<p>Keep navigation relative to avoid hardcoding URLs.</p>
</li>
</ul>
</div>
</div>
<div class="sect2">
<h3 id="_programmatic_navigation_that_reads_well">Programmatic navigation that reads well</h3>
<div class="paragraph">
<p>When you need to route from code, favor clarity and explicitness.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-typescript" data-lang="typescript">// features/auth/login.component.ts (snippet)
import { Component, inject } from '@angular/core';
import { ActivatedRoute, Router } from '@angular/router';
import { AuthService } from './auth.service';

@Component({
  standalone: true,
  template: `
    &lt;form (ngSubmit)="login()"&gt;
      &lt;!-- form fields --&gt;
      &lt;button type="submit"&gt;Sign in&lt;/button&gt;
    &lt;/form&gt;
  `,
})
export class LoginComponent {
  private router = inject(Router);
  private route = inject(ActivatedRoute);
  private auth = inject(AuthService);

  async login() {
    await this.auth.signIn();
    const redirect = this.route.snapshot.queryParamMap.get('redirect') || '/dashboard';
    this.router.navigateByUrl(redirect, { replaceUrl: true, state: { from: 'login' } });
  }
}</code></pre>
</div>
</div>
<div class="ulist">
<ul>
<li>
<p>navigate and navigateByUrl are both fine; navigate works with command arrays and relative routes.</p>
</li>
<li>
<p>replaceUrl avoids filling history with transient steps like login.</p>
</li>
</ul>
</div>
</div>
<div class="sect2">
<h3 id="_route_guards_protect_match_and_confirm">Route guards: protect, match, and confirm</h3>
<div class="paragraph">
<p>Functional guards are terse, testable, and DI-friendly. Use canActivate for already-loaded routes and canMatch to gate access before lazy-loading. Use canDeactivate to protect against losing changes.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-typescript" data-lang="typescript">// app/auth/guards.ts
import { inject } from '@angular/core';
import { CanActivateFn, CanDeactivateFn, CanMatchFn, Router, UrlSegment, Route } from '@angular/router';
import { AuthService } from './auth.service';

export const authCanActivate: CanActivateFn = (_route, state) =&gt; {
  const auth = inject(AuthService);
  const router = inject(Router);
  if (auth.isLoggedIn()) return true;
  // Return a UrlTree to redirect without throwing
  return router.createUrlTree(['/login'], { queryParams: { redirect: state.url } });
};

export const authCanMatch: CanMatchFn = (route: Route, segments: UrlSegment[]) =&gt; {
  const auth = inject(AuthService);
  const router = inject(Router);
  if (auth.isLoggedIn()) return true;

  const attempted = '/' + segments.map(s =&gt; s.path).join('/');
  return router.createUrlTree(['/login'], { queryParams: { redirect: attempted } });
};

export const unsavedCanDeactivate: CanDeactivateFn&lt;{ hasUnsavedChanges(): boolean }&gt; = (component) =&gt; {
  return component.hasUnsavedChanges()
    ? confirm('You have unsaved changes. Leave this page?')
    : true;
};</code></pre>
</div>
</div>
<div class="paragraph">
<p>Notes:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>Returning a UrlTree is the most ergonomic way to redirect from guards.</p>
</li>
<li>
<p>Prefer canMatch for lazy-loaded feature entries. It prevents loading code the user can’t access.</p>
</li>
</ul>
</div>
</div>
<div class="sect2">
<h3 id="_async_redirects_in_angular_20">Async redirects in Angular 20</h3>
<div class="paragraph">
<p>Redirects are often conditional and data-driven. Angular 20 refines ergonomics for async redirects by allowing redirect functions to return a Promise or Observable of a UrlTree, keeping logic declarative in the route table. When you need Dependency Injection, the function executes in a proper injection context.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-typescript" data-lang="typescript">// app/app.routes.ts (excerpt showing async redirect)
import { Router, Routes } from '@angular/router';
import { inject } from '@angular/core';
import { AuthService } from './auth/auth.service';

export const routes: Routes = [
  // ...
  {
    path: 'start',
    // Async redirect based on login status
    redirectTo: async () =&gt; {
      const auth = inject(AuthService);
      const router = inject(Router);
      const isLoggedIn = await auth.isLoggedInOnce(); // e.g., resolves after token refresh
      return isLoggedIn
        ? router.createUrlTree(['/dashboard'])
        : router.createUrlTree(['/login'], { queryParams: { redirect: '/start' } });
    },
    pathMatch: 'full',
  },
  // ...
];</code></pre>
</div>
</div>
<div class="paragraph">
<p>If your team prefers explicit control (or for compatibility), use canMatch to perform the same async decision and return a UrlTree. Both approaches keep “redirect intent” within the routing layer, preserving a clear separation from UI.</p>
</div>
</div>
<div class="sect2">
<h3 id="_handling_404s_and_fallbacks">Handling 404s and fallbacks</h3>
<div class="paragraph">
<p>Keep a final catch-all route at the end. Make the not-found component tiny and isolated.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-typescript" data-lang="typescript">// shared/not-found/not-found.component.ts
import { Component } from '@angular/core';

@Component({
  standalone: true,
  template: `
    &lt;h2&gt;Page not found&lt;/h2&gt;
    &lt;p&gt;The page you’re looking for doesn’t exist.&lt;/p&gt;
    &lt;a routerLink="/home"&gt;Go to Home&lt;/a&gt;
  `,
})
export class NotFoundComponent {}</code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="_developer_experience_tips_that_scale">Developer experience tips that scale</h3>
<div class="ulist">
<ul>
<li>
<p>Title and data: Use the route title for sensible defaults. Keep route data small and serializable.</p>
</li>
<li>
<p>Preloading: withPreloading(PreloadAllModules) improves perceived speed after the first screen.</p>
</li>
<li>
<p>Guard reuse: Share a single predicate behind multiple guard types (e.g., canActivate and canMatch) to avoid drift.</p>
</li>
<li>
<p>UrlTree over side effects: Prefer returning UrlTree over imperative router.navigate inside guards.</p>
</li>
<li>
<p>Relative navigation: Favor relativeTo where possible to avoid brittle absolute paths.</p>
</li>
<li>
<p>Observability: Listen to router.events for tracing NavigationStart, NavigationEnd, NavigationCancel when debugging.</p>
</li>
</ul>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-typescript" data-lang="typescript">// Simple router event logging helper (dev only)
import { filter } from 'rxjs';
import { Router, NavigationStart, NavigationEnd, NavigationCancel } from '@angular/router';

export function logNavigation(router: Router) {
  router.events
    .pipe(filter(e =&gt; e instanceof NavigationStart || e instanceof NavigationEnd || e instanceof NavigationCancel))
    .subscribe(e =&gt; console.debug('[router]', e));
}</code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="_common_pitfalls_and_guardrails">Common pitfalls and guardrails</h3>
<div class="ulist">
<ul>
<li>
<p>Infinite redirect loops: Always check target vs current URL when redirecting conditionally. Returning the same UrlTree repeatedly will stall navigation.</p>
</li>
<li>
<p>Missing pathMatch: For empty-path redirects, pathMatch: 'full' prevents partial matches from hijacking nested routes.</p>
</li>
<li>
<p>Eager vs lazy: Use canMatch for feature entries to avoid loading code for unauthorized users.</p>
</li>
<li>
<p>Query params and state: Preserve user intent via redirect query params. Clear them after successful navigation if they’re transient.</p>
</li>
</ul>
</div>
</div>
<div class="sect2">
<h3 id="_putting_it_together_a_cohesive_flow">Putting it together: a cohesive flow</h3>
<div class="ulist">
<ul>
<li>
<p>Users hitting /start are asynchronously redirected based on auth state using async redirects.</p>
</li>
<li>
<p>Unauthenticated users attempting /projects are intercepted by canMatch and sent to /login with a redirect back.</p>
</li>
<li>
<p>Settings protects against accidental loss via canDeactivate.</p>
</li>
<li>
<p>Dashboard and Projects load lazily, preloaded after the first screen.</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>This balances UX and performance while keeping the routing layer the single source of truth for navigation logic.</p>
</div>
</div>
<div class="sect1">
<h2 id="_conclusion">Conclusion</h2>
<div class="sectionbody">
<div class="paragraph">
<p>A well-structured router is more than a URL switchboard, it’s an agreement about flow, access, and intent. Angular’s modern APIs make routing readable and testable: standalone routes, functional route guards, lazy-loading, and async redirects that keep decisions close to configuration. When your code communicates clearly, your team moves faster and makes fewer mistakes.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_next_steps">Next Steps</h2>
<div class="sectionbody">
<div class="ulist">
<ul>
<li>
<p>Extract guard predicates into pure functions and unit test them with dependency mocks.</p>
</li>
<li>
<p>Add a data resolver where you need the route to wait for critical data before rendering.</p>
</li>
<li>
<p>Introduce a prefetch strategy for specific features, or preload on hover using quicklink-style heuristics.</p>
</li>
<li>
<p>Explore view transitions with router integration to smooth screen changes.</p>
</li>
<li>
<p>Audit routes for consistent titles, data contracts, and error handling paths.</p>
</li>
</ul>
</div>
</div>
</div>
<]]></content:encoded>
					
		
		
			</item>
         
	<item>
		<title>Data Binding in Angular: Templates, Interpolation, and Property/Event Binding</title>
		<link>https://blog.lunatech.com//posts/2025-10-15-data-binding-in-angular-templates-interpolation-and-propertyevent-binding</link>
		
		<dc:creator><![CDATA[Jake Ortega]]></dc:creator>
        <pubDate>2025-10-15T00:00:00.000Z</pubDate>
         
             {
            <category><![CDATA[Beginner]]></category>
                }
             {
            <category><![CDATA[property binding]]></category>
                }
             {
            <category><![CDATA[event binding]]></category>
                }
             {
            <category><![CDATA[interpolation]]></category>
                }
             {
            <category><![CDATA[template syntax]]></category>
                }
             {
            <category><![CDATA[en]]></category>
                }
             
        
		<guid isPermaLink="false">https://blog.lunatech.com//posts/2025-10-15-data-binding-in-angular-templates-interpolation-and-propertyevent-binding</guid>

					<description>
                        <![CDATA[ Data binding is the heartbeat of Angular templates. Learn how data flows between components and templates using interpolation, property binding, event binding, and two-way binding. This topic also introduces new Angular 20 template features like template literals. We’ll keep the focus practical: clear patterns, minimal surprises, and maintainable code that scales.]]></description>
                    <content:encoded><![CDATA[
                    <div id="preamble">
<div class="sectionbody">
<div class="paragraph">
<p>Data binding is the heartbeat of Angular templates. Learn how data flows between components and templates using interpolation, property binding, event binding, and two-way binding. This topic also introduces new Angular 20 template features like template literals. We’ll keep the focus practical: clear patterns, minimal surprises, and maintainable code that scales.</p>
</div>
</div>
</div>
<div class="sect2">
<h3 id="_the_mental_model_unidirectional_data_flow_well_timed_feedback">The mental model: unidirectional data flow, well-timed feedback</h3>
<div class="ulist">
<ul>
<li>
<p>From component to view: interpolation and property binding render state.</p>
</li>
<li>
<p>From view to component: event binding captures user intent.</p>
</li>
<li>
<p>Two-way binding is a convenience that composes the two, not a separate mechanism.</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>Favor predictable one-way flows; reach for two-way when it improves clarity without hiding complexity.</p>
</div>
</div>
<div class="sect2">
<h3 id="_interpolation_simple_readable_one_way_display">Interpolation: simple, readable, one-way display</h3>
<div class="paragraph">
<p>Interpolation renders values into text nodes using template syntax like {{ &#8230;&#8203; }}. It’s ideal for human-readable content.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-html" data-lang="html">&lt;h2&gt;{{ title }}&lt;/h2&gt;
&lt;p&gt;Welcome, {{ user?.name ?? 'Guest' }}.&lt;/p&gt;
&lt;p&gt;Subtotal: {{ price | currency: 'USD' }}&lt;/p&gt;</code></pre>
</div>
</div>
<div class="paragraph">
<p>Guidelines:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>Keep expressions simple. Avoid calling methods that do non-trivial work.</p>
</li>
<li>
<p>Use pipes for presentation logic (formatting, slicing, etc.).</p>
</li>
<li>
<p>Use the safe-navigation operator (?.) to avoid null/undefined errors at render time.</p>
</li>
</ul>
</div>
<div class="sect3">
<h4 id="_angular_20_template_literals_in_expressions">Angular 20 template literals in expressions</h4>
<div class="paragraph">
<p>Angular 20 enables JavaScript-style template literals inside template expressions for more expressive string composition.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-html" data-lang="html">&lt;h2&gt;{{ `${greeting}, ${user?.firstName || 'friend'}!` }}&lt;/h2&gt;
&lt;button [attr.aria-label]="`Open details for ${item.title}`"&gt;Open&lt;/button&gt;</code></pre>
</div>
</div>
<div class="paragraph">
<p>Use them for readable, localized strings or ARIA attributes. Keep them concise. If you’re building complex messages, consider a dedicated formatter or i18n.</p>
</div>
</div>
</div>
<div class="sect2">
<h3 id="_property_binding_write_to_dom_and_component_inputs">Property binding: write to DOM and component inputs</h3>
<div class="paragraph">
<p>Property binding uses square brackets to set DOM properties, ARIA attributes, styles, classes, and child component inputs.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-html" data-lang="html">&lt;!-- DOM properties --&gt;
&lt;input [value]="query()" [disabled]="isSubmitting()" /&gt;

&lt;!-- Attributes and accessibility --&gt;
&lt;button [attr.aria-pressed]="isActive" [attr.data-id]="item.id"&gt;Toggle&lt;/button&gt;

&lt;!-- Classes and styles --&gt;
&lt;div [class.active]="isActive" [style.width.px]="panelWidth"&gt;&lt;/div&gt;

&lt;!-- Child component inputs --&gt;
&lt;app-avatar [src]="user.photoUrl" [alt]="user.name" [size]="64"&gt;&lt;/app-avatar&gt;</code></pre>
</div>
</div>
<div class="paragraph">
<p>Under the hood, Angular binds to the actual property when available (safer and more correct than raw attributes). Use [attr.*] only when there is no matching property.</p>
</div>
<div class="sect3">
<h4 id="_signals_play_nicely_with_bindings">Signals play nicely with bindings</h4>
<div class="paragraph">
<p>Signals provide push-based reactivity. Call them in templates to read their current value.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-typescript" data-lang="typescript">import { ChangeDetectionStrategy, Component, computed, signal } from '@angular/core';

@Component({
  selector: 'app-search',
  standalone: true,
  changeDetection: ChangeDetectionStrategy.OnPush,
  template: `
    &lt;label&gt;
      Query:
      &lt;input [value]="query()" (input)="onInput($event)" placeholder="Type to search..." /&gt;
    &lt;/label&gt;

    @if (filtered().length === 0) {
      &lt;p&gt;No results&lt;/p&gt;
    } @else {
      &lt;ul&gt;
        @for (item of filtered(); track item) {
          &lt;li&gt;{{ item }}&lt;/li&gt;
        }
      &lt;/ul&gt;
    }
  `
})
export class SearchComponent {
  readonly items = signal(['apple', 'banana', 'citrus', 'date', 'elderberry']);
  readonly query = signal('');
  readonly filtered = computed(() =&gt;
    this.items().filter(v =&gt; v.toLowerCase().includes(this.query().toLowerCase()))
  );

  onInput(event: Event) {
    const input = event.target as HTMLInputElement;
    this.query.set(input.value);
  }
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>Note:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>Property binding [value]="query()" reads the signal.</p>
</li>
<li>
<p>Event binding (input)="&#8230;&#8203;" updates the signal.</p>
</li>
<li>
<p>Built-in control flow (@if and @for) keeps the template declarative and fast.</p>
</li>
</ul>
</div>
</div>
</div>
<div class="sect2">
<h3 id="_event_binding_user_intent_back_to_the_component">Event binding: user intent back to the component</h3>
<div class="paragraph">
<p>Event binding uses parentheses to listen to DOM or component events.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-html" data-lang="html">&lt;button (click)="toggle()"&gt;{{ isOpen ? 'Close' : 'Open' }}&lt;/button&gt;
&lt;input (keydown.enter)="submit()" /&gt;
&lt;input (input)="onInput($event)" /&gt;</code></pre>
</div>
</div>
<div class="paragraph">
<p>Type your handlers for safety and clarity.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-typescript" data-lang="typescript">toggle(): void {
  this.isOpen = !this.isOpen;
}

submit(): void {
  if (!this.formValid) return;
  this.save();
}

onInput(event: Event): void {
  const target = event.target as HTMLInputElement;
  this.value = target.value;
}</code></pre>
</div>
</div>
<div class="ulist">
<ul>
<li>
<p>Prefer specific event names like keydown.enter for intent-revealing handlers.</p>
</li>
<li>
<p>Avoid expensive work inside template expressions; do it in component methods or computed signals.</p>
</li>
</ul>
</div>
</div>
<div class="sect2">
<h3 id="_two_way_binding_when_it_helps_use_it_intentionally">Two-way binding: when it helps, use it intentionally</h3>
<div class="paragraph">
<p>Two-way binding composes property binding and event binding into a single banana-in-a-box syntax.</p>
</div>
<div class="sect3">
<h4 id="_with_forms_ngmodel">With forms (ngModel)</h4>
<div class="paragraph">
<p>This is convenient in simple forms. Import FormsModule in standalone components.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-typescript" data-lang="typescript">import { Component } from '@angular/core';
import { FormsModule } from '@angular/forms';

@Component({
  selector: 'app-preferences',
  standalone: true,
  imports: [FormsModule],
  template: `
    &lt;label&gt;Nickname: &lt;input [(ngModel)]="nickname" /&gt;&lt;/label&gt;
    &lt;label&gt;
      &lt;input type="checkbox" [(ngModel)]="emailOptIn" /&gt;
      Email me updates
    &lt;/label&gt;
    &lt;p&gt;Preview: {{ nickname }} (opt-in: {{ emailOptIn }})&lt;/p&gt;
  `
})
export class PreferencesComponent {
  nickname = '';
  emailOptIn = true;
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>With signals, bridge two-way binding by pairing [ngModel] and (ngModelChange):</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-html" data-lang="html">&lt;input [ngModel]="query()" (ngModelChange)="query.set($event)" /&gt;</code></pre>
</div>
</div>
</div>
<div class="sect3">
<h4 id="_custom_two_way_binding_for_child_components">Custom two-way binding for child components</h4>
<div class="paragraph">
<p>Define a pair of Input and Output with the Change suffix. Angular will recognize [(value)].</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-typescript" data-lang="typescript">import { Component, EventEmitter, Input, Output } from '@angular/core';
import { CommonModule } from '@angular/common';

@Component({
  selector: 'app-rating',
  standalone: true,
  imports: [CommonModule],
  template: `
    &lt;div class="stars"&gt;
      &lt;button *ngFor="let s of [1,2,3,4,5]"
              type="button"
              [class.filled]="s &lt;= value"
              (click)="setValue(s)"
              [attr.aria-label]="'Set rating to ' + s"&gt;
        ★
      &lt;/button&gt;
    &lt;/div&gt;
  `,
  styles: [`.filled { color: #f59e0b; } button { background:none; border:none; font-size:1.25rem; cursor:pointer; }`]
})
export class RatingComponent {
  @Input() value = 0;
  @Output() valueChange = new EventEmitter&lt;number&gt;();

  setValue(v: number) {
    this.value = v;
    this.valueChange.emit(v);
  }
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>Parent usage:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-html" data-lang="html">&lt;app-rating [(value)]="product.rating"&gt;&lt;/app-rating&gt;
&lt;p&gt;Current rating: {{ product.rating }}&lt;/p&gt;</code></pre>
</div>
</div>
<div class="paragraph">
<p>Tip: If your project uses the signal-based inputs API, the model() helper can reduce boilerplate. The classic pair above remains broadly compatible and explicit.</p>
</div>
</div>
</div>
<div class="sect2">
<h3 id="_template_syntax_patterns_that_scale">Template syntax patterns that scale</h3>
<div class="ulist">
<ul>
<li>
<p>Keep expressions pure and cheap. Avoid calling functions that allocate arrays or perform filtering on each change detection; use computed signals or memoized selectors.</p>
</li>
<li>
<p>Bind to properties, not attributes. Prefer [value], [disabled], [checked] over [attr.value], except when no property exists.</p>
</li>
<li>
<p>Use track with @for to avoid re-rendering stable items:
@for (item of items; track item.id) { &#8230;&#8203; }</p>
</li>
<li>
<p>For [innerHTML], sanitize or trust only safe content. Angular’s DomSanitizer exists for exceptional cases—prefer plain text whenever possible.</p>
</li>
</ul>
</div>
</div>
<div class="sect2">
<h3 id="_angular_20_template_literal_examples_in_context">Angular 20 template literal examples in context</h3>
<div class="paragraph">
<p>Use template literals where they improve clarity, especially for ARIA and labeling.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-html" data-lang="html">&lt;!-- Readable, localized-friendly labels --&gt;
&lt;button
  type="button"
  [attr.aria-label]="`${isPlaying ? 'Pause' : 'Play'} ${track.title}`"
  (click)="togglePlay()"&gt;
  {{ isPlaying ? 'Pause' : 'Play' }}
&lt;/button&gt;

&lt;!-- Combining with pipes --&gt;
&lt;p&gt;{{ `Hello, ${user?.name || 'Guest'}` | titlecase }}&lt;/p&gt;

&lt;!-- Attributes that aren’t DOM properties --&gt;
&lt;a [attr.data-test-id]="`link-${link.id}`" [href]="link.url"&gt;{{ link.title }}&lt;/a&gt;</code></pre>
</div>
</div>
<div class="paragraph">
<p>Keep logic minimal; push complex decisions into the component or computed signals for testability.</p>
</div>
</div>
<div class="sect2">
<h3 id="_a_cohesive_example_binding_the_pieces">A cohesive example: binding the pieces</h3>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-typescript" data-lang="typescript">import { ChangeDetectionStrategy, Component, signal } from '@angular/core';
import { CommonModule } from '@angular/common';
import { FormsModule } from '@angular/forms';
import { RatingComponent } from './rating.component';

@Component({
  selector: 'app-product-card',
  standalone: true,
  imports: [CommonModule, FormsModule, RatingComponent],
  changeDetection: ChangeDetectionStrategy.OnPush,
  template: `
    &lt;article class="card"&gt;
      &lt;header&gt;
        &lt;h3&gt;{{ product().name }}&lt;/h3&gt;
        &lt;p class="price"&gt;{{ product().price | currency:'USD' }}&lt;/p&gt;
      &lt;/header&gt;

      &lt;label [attr.aria-label]="`Quantity for ${product().name}`"&gt;
        Qty:
        &lt;input type="number"
               min="1"
               [ngModel]="qty()"
               (ngModelChange)="qty.set($event)" /&gt;
      &lt;/label&gt;

      &lt;app-rating [(value)]="rating"&gt;&lt;/app-rating&gt;

      &lt;p&gt;{{ description }}&lt;/p&gt;

      &lt;button type="button"
              class="add"
              [disabled]="isSubmitting()"
              (click)="addToCart()"&gt;
        {{ isSubmitting() ? 'Adding…' : 'Add to cart' }}
      &lt;/button&gt;
    &lt;/article&gt;
  `,
  styles: [`.card{border:1px solid #e5e7eb;border-radius:.5rem;padding:1rem}.price{color:#374151}.add{margin-top:.75rem}`]
})
export class ProductCardComponent {
  readonly product = signal({ id: 1, name: 'Noise-canceling Headphones', price: 199.99 });
  readonly qty = signal(1);
  rating = 4; // two-way bound to child
  readonly isSubmitting = signal(false);

  get description(): string {
    return `${this.product().name} — rated ${this.rating}/5 by our customers.`;
  }

  async addToCart() {
    this.isSubmitting.set(true);
    try {
      await fakeHttpPost({
        id: this.product().id,
        qty: this.qty(),
        rating: this.rating
      });
    } finally {
      this.isSubmitting.set(false);
    }
  }
}

function fakeHttpPost(payload: unknown) {
  return new Promise&lt;void&gt;(r =&gt; setTimeout(r, 500));
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>What you see:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>Interpolation renders human-readable fields.</p>
</li>
<li>
<p>Property binding controls input state and disabled state.</p>
</li>
<li>
<p>Event binding processes clicks and model changes.</p>
</li>
<li>
<p>Two-way binding streamlines rating updates.</p>
</li>
<li>
<p>Template literals keep labels clear and accessible.</p>
</li>
</ul>
</div>
</div>
<div class="sect2">
<h3 id="_conclusion">Conclusion</h3>
<div class="paragraph">
<p>Data binding is how intent flows through your Angular app. Interpolation and property binding project state. Event binding captures change. Two-way binding composes both when it reduces friction. With Angular 20’s template literal support, you can craft clearer strings and ARIA labels without sacrificing readability. Keep expressions simple, push complexity into components or computed signals, and lean on built-in control flow for performance.</p>
</div>
</div>
<div class="sect2">
<h3 id="_next_steps">Next Steps</h3>
<div class="ulist">
<ul>
<li>
<p>Audit a component for heavy template expressions. Move logic into computed signals or pure methods.</p>
</li>
<li>
<p>Add ARIA attributes with property binding and template literals to improve accessibility.</p>
</li>
<li>
<p>Refactor a custom control to support [(value)] using the input/output pair.</p>
</li>
<li>
<p>Explore Angular’s built-in control flow (@if, @for, @switch) to reduce directive boilerplate.</p>
</li>
<li>
<p>If your team uses signals broadly, standardize patterns for bridging with forms: [ngModel] + (ngModelChange) for crisp two-way behavior.</p>
</li>
</ul>
</div>
</div>
<]]></content:encoded>
					
		
		
			</item>
         
	<item>
		<title>Getting Started with Angular 19: Your First Signals-Powered App</title>
		<link>https://blog.lunatech.com//posts/2025-10-12-getting-started-with-angular-19--your-first-signals-powered-app</link>
		
		<dc:creator><![CDATA[Jake Ortega]]></dc:creator>
        <pubDate>2025-10-12T00:00:00.000Z</pubDate>
         
             {
            <category><![CDATA[angular basics]]></category>
                }
             {
            <category><![CDATA[signals]]></category>
                }
             {
            <category><![CDATA[reactive state]]></category>
                }
             {
            <category><![CDATA[en]]></category>
                }
             
        
		<guid isPermaLink="false">https://blog.lunatech.com//posts/2025-10-12-getting-started-with-angular-19--your-first-signals-powered-app</guid>

					<description>
                        <![CDATA[ Angular 19 makes signals a first-class, ergonomic way to manage reactive state—without the ceremony many of us associate with using RxJS for every problem. In this guide, you’ll build a small, production-quality feature using signals, computed values, and effects, sticking to Angular basics while practicing patterns you’ll reuse in real apps. Think of it as your “hello world” for signals, with enough structure to scale.]]></description>
                    <content:encoded><![CDATA[
                    <div id="preamble">
<div class="sectionbody">
<div class="paragraph">
<p>Angular 19 makes signals a first-class, ergonomic way to manage reactive state—without the ceremony many of us associate with using RxJS for every problem. In this guide, you’ll build a small, production-quality feature using signals, computed values, and effects, sticking to Angular basics while practicing patterns you’ll reuse in real apps. Think of it as your “hello world” for signals, with enough structure to scale.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_why_signals_for_your_first_angular_19_app">Why signals for your first Angular 19 app</h2>
<div class="sectionbody">
<div class="paragraph">
<p>Signals shine when:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>You want local or feature-level state that’s easy to understand and test.</p>
</li>
<li>
<p>You prefer declarative data flow with minimal boilerplate.</p>
</li>
<li>
<p>You care about performance and predictable change detection.</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>Signals give you:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>signal(): a mutable value you set and read like a variable.</p>
</li>
<li>
<p>computed(): a derived value that automatically recalculates when dependencies change.</p>
</li>
<li>
<p>effect(): a side effect that runs when its dependent signals change (think persistence, logging, analytics).</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>With the built-in control flow (@if, @for, @switch), Angular templates read signals naturally and concisely—no async pipe or manual subscriptions required.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_what_were_building">What we’re building</h2>
<div class="sectionbody">
<div class="paragraph">
<p>A tiny yet complete “Tasks” feature:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>Add tasks, toggle done, filter by status.</p>
</li>
<li>
<p>Persist to localStorage.</p>
</li>
<li>
<p>Derive stats via computed signals.</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>We’ll use:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>Standalone components.</p>
</li>
<li>
<p>inject() for dependency injection.</p>
</li>
<li>
<p>Signals for reactive state.</p>
</li>
<li>
<p>New template control flow.</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>If you’re comfortable with Angular basics (components, templates, DI), you’re good to go.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_app_structure">App structure</h2>
<div class="sectionbody">
<div class="ulist">
<ul>
<li>
<p>TaskStore: a signals-powered service for state and business logic.</p>
</li>
<li>
<p>AppComponent: a standalone component that renders the UI and interacts with the store.</p>
</li>
<li>
<p>main.ts: bootstraps the app.</p>
</li>
</ul>
</div>
<div class="sect2">
<h3 id="_taskstore_reactive_state_with_signals">TaskStore: reactive state with signals</h3>
<div class="paragraph">
<p>We’ll keep domain logic, mutations, and persistence here—a clean separation from the component.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-typescript" data-lang="typescript">import { Injectable, computed, effect, signal } from '@angular/core';

export type TaskFilter = 'all' | 'open' | 'done';

export interface Task {
  id: string;
  title: string;
  done: boolean;
}

function loadTasks(): Task[] {
  try {
    const raw = localStorage.getItem('tasks.v1');
    return raw ? JSON.parse(raw) as Task[] : [];
  } catch {
    return [];
  }
}

@Injectable({ providedIn: 'root' })
export class TaskStore {
  // Source signals
  private readonly tasks = signal&lt;Task[]&gt;(loadTasks());
  readonly filter = signal&lt;TaskFilter&gt;('all');

  // Derived reactive state
  readonly stats = computed(() =&gt; {
    const list = this.tasks();
    const done = list.filter(t =&gt; t.done).length;
    const open = list.length - done;
    return { total: list.length, open, done };
  });

  readonly filtered = computed(() =&gt; {
    const f = this.filter();
    const list = this.tasks();
    if (f === 'open') return list.filter(t =&gt; !t.done);
    if (f === 'done') return list.filter(t =&gt; t.done);
    return list;
  });

  // Persist tasks whenever they change
  private readonly persist = effect(() =&gt; {
    const current = this.tasks();
    localStorage.setItem('tasks.v1', JSON.stringify(current));
  });

  add(title: string) {
    const clean = title.trim();
    if (!clean) return;
    const newTask: Task = { id: crypto.randomUUID(), title: clean, done: false };
    this.tasks.update(list =&gt; [newTask, ...list]);
  }

  toggle(id: string) {
    this.tasks.update(list =&gt;
      list.map(t =&gt; (t.id === id ? { ...t, done: !t.done } : t))
    );
  }

  remove(id: string) {
    this.tasks.update(list =&gt; list.filter(t =&gt; t.id !== id));
  }

  clearDone() {
    this.tasks.update(list =&gt; list.filter(t =&gt; !t.done));
  }

  // Expose readonly getters where helpful
  get all() { return this.tasks.asReadonly(); }
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>Notes:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>Keep tasks private, expose asReadonly() if needed, and route all mutations through methods. That protects invariants and makes tests straightforward.</p>
</li>
<li>
<p>computed() caches until dependencies change, so stats and filtered are cheap to read in templates.</p>
</li>
<li>
<p>effect() is for side effects only. Don’t derive data there.</p>
</li>
</ul>
</div>
</div>
<div class="sect2">
<h3 id="_appcomponent_template_first_with_control_flow">AppComponent: template-first with control flow</h3>
<div class="paragraph">
<p>The component stays lean: read signals, call store methods, and keep the markup honest. No subscriptions and no manual change detection.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-typescript" data-lang="typescript">import { Component, inject } from '@angular/core';
import { TaskStore, TaskFilter } from './task.store';

@Component({
  selector: 'app-root',
  standalone: true,
  templateUrl: './app.component.html',
})
export class AppComponent {
  readonly store = inject(TaskStore);

  setFilter(f: TaskFilter) {
    this.store.filter.set(f);
  }

  add(input: HTMLInputElement) {
    this.store.add(input.value);
    input.value = '';
    input.focus();
  }
}</code></pre>
</div>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-html" data-lang="html">&lt;header class="app-header"&gt;
  &lt;h1&gt;Tasks (Signals)&lt;/h1&gt;
  &lt;p&gt;
    Total: {{ store.stats().total }}
    • Open: {{ store.stats().open }}
    • Done: {{ store.stats().done }}
  &lt;/p&gt;
&lt;/header&gt;

&lt;section class="task-create"&gt;
  &lt;input
    #title
    type="text"
    placeholder="Add a task and press Enter"
    (keyup.enter)="add(title)"
    aria-label="New task title" /&gt;
  &lt;button (click)="add(title)"&gt;Add&lt;/button&gt;
&lt;/section&gt;

&lt;nav class="filters"&gt;
  &lt;button (click)="setFilter('all')" [class.active]="store.filter() === 'all'"&gt;All&lt;/button&gt;
  &lt;button (click)="setFilter('open')" [class.active]="store.filter() === 'open'"&gt;Open&lt;/button&gt;
  &lt;button (click)="setFilter('done')" [class.active]="store.filter() === 'done'"&gt;Done&lt;/button&gt;
&lt;/nav&gt;

&lt;section class="task-list"&gt;
  @if (store.filtered().length === 0) {
    &lt;p class="empty"&gt;No tasks to show.&lt;/p&gt;
  } @else {
    &lt;ul&gt;
      @for (task of store.filtered(); track task.id) {
        &lt;li&gt;
          &lt;label&gt;
            &lt;input type="checkbox" [checked]="task.done" (change)="store.toggle(task.id)" /&gt;
            &lt;span [class.done]="task.done"&gt;{{ task.title }}&lt;/span&gt;
          &lt;/label&gt;
          &lt;button class="remove" (click)="store.remove(task.id)" aria-label="Remove task"&gt;✕&lt;/button&gt;
        &lt;/li&gt;
      }
    &lt;/ul&gt;
  }
&lt;/section&gt;

&lt;footer class="actions"&gt;
  &lt;button (click)="store.clearDone()" [disabled]="store.stats().done === 0"&gt;
    Clear completed
  &lt;/button&gt;
&lt;/footer&gt;</code></pre>
</div>
</div>
<div class="paragraph">
<p>A few things to notice:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>Reading a signal in a template uses function-call syntax: store.stats().</p>
</li>
<li>
<p>The new @if and @for syntax is concise and fast; track by a stable id to minimize DOM churn.</p>
</li>
<li>
<p>We avoid ngModel here to keep the example lean; use reactive forms if you need validation and composition.</p>
</li>
</ul>
</div>
</div>
<div class="sect2">
<h3 id="_bootstrap">Bootstrap</h3>
<div class="paragraph">
<p>With standalone components, the bootstrap is pleasantly thin.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-typescript" data-lang="typescript">import { bootstrapApplication } from '@angular/platform-browser';
import { AppComponent } from './app.component';

bootstrapApplication(AppComponent).catch(err =&gt; console.error(err));</code></pre>
</div>
</div>
<div class="paragraph">
<p>That’s it. No NgModule, no extra ceremony. In a larger app, you’d layer in provideRouter, HTTP, and other providers here.</p>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_developer_experience_and_design_notes">Developer experience and design notes</h2>
<div class="sectionbody">
<div class="paragraph">
<p>From real projects migrating to signals and the new control flow, a few principles keep teams productive:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>Keep mutations small and intention-revealing.</p>
</li>
<li>
<p>add, toggle, remove, clearDone communicate behavior explicitly.</p>
</li>
<li>
<p>Encapsulate shape and invariants in your store; keep the component mostly declarative.</p>
</li>
<li>
<p>Use computed for any value you want to “feel like” state in the template.</p>
</li>
<li>
<p>stats and filtered are cheap to read and always consistent.</p>
</li>
<li>
<p>Avoid doing ad-hoc filtering in templates; it’s harder to optimize and test.</p>
</li>
<li>
<p>Reserve effect for I/O and cross-cutting behavior.</p>
</li>
<li>
<p>Persistence, analytics, message bus publishing—great uses of effect.</p>
</li>
<li>
<p>Don’t compute UI data inside effect; that’s what computed is for.</p>
</li>
<li>
<p>Prefer signals for local/feature reactive state, embrace RxJS where it fits.</p>
</li>
<li>
<p>Signals are excellent for UI state and domain mutations.</p>
</li>
<li>
<p>Streams still shine for event composition, websockets, and complex async flows.</p>
</li>
<li>
<p>Interop utilities exist if you need to bridge; start simple.</p>
</li>
<li>
<p>Track by stable ids in @for.</p>
</li>
<li>
<p>You’ll avoid unnecessary re-renders and improve perceived performance.</p>
</li>
<li>
<p>Keep templates dumb.</p>
</li>
<li>
<p>Let the store manage logic; your templates will stay readable, and testing gets easier.</p>
</li>
</ul>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_testing_the_store">Testing the store</h2>
<div class="sectionbody">
<div class="paragraph">
<p>Signals play nicely with unit tests because there’s no hidden subscription machinery to manage.</p>
</div>
<div class="ulist">
<ul>
<li>
<p>Instantiate TaskStore directly, call methods, and assert on taskStore.filtered(), taskStore.stats(), etc.</p>
</li>
<li>
<p>If an effect writes to localStorage, consider injecting a light persistence adapter so you can stub it in tests. For this article’s simplicity, we wrote to localStorage directly; in production, prefer an injected storage port.</p>
</li>
</ul>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_where_this_scales">Where this scales</h2>
<div class="sectionbody">
<div class="paragraph">
<p>This pattern scales surprisingly far:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>Add tags or due dates? Extend Task and update computed accordingly.</p>
</li>
<li>
<p>Need a multi-page app? Provide routes and lazy-load feature components while keeping a small, focused store per feature.</p>
</li>
<li>
<p>Want undo/redo? Wrap mutations to capture patches and provide intent-level commands.</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>Signals help you move faster because the mental model is simple: read values, change values, derive values. It’s the right default for many UI flows.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_common_pitfalls_to_avoid">Common pitfalls to avoid</h2>
<div class="sectionbody">
<div class="ulist">
<ul>
<li>
<p>Overusing effect for data derivation. If you find yourself setting signals inside an effect just to compute something, reach for computed instead.</p>
</li>
<li>
<p>Mixing many mutable signals in components. Prefer a single cohesive store per feature or sub-feature.</p>
</li>
<li>
<p>Forgetting to track by id in @for. It’s a small habit with big performance wins.</p>
</li>
</ul>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_conclusion">Conclusion</h2>
<div class="sectionbody">
<div class="paragraph">
<p>Getting started with Angular 19 and signals doesn’t require a framework rewrite. By leaning on a simple TaskStore and a lean component using the new control flow, we built a small but complete feature with clear reactive state and minimal boilerplate. This is the kind of foundation that keeps teams sane as apps grow—explicit mutations, derived state where it belongs, and templates that read like a story.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_next_steps">Next Steps</h2>
<div class="sectionbody">
<div class="ulist">
<ul>
<li>
<p>Add a search signal and a computed that combines filter + search.</p>
</li>
<li>
<p>Extract persistence into an injected storage service and mock it in unit tests.</p>
</li>
<li>
<p>Introduce provideRouter and split the UI into feature routes.</p>
</li>
<li>
<p>Integrate reactive forms for validation on create/edit flows.</p>
</li>
<li>
<p>Explore interop with RxJS for server events or HTTP polling, using signals at the edges.</p>
</li>
<li>
<p>Measure with Angular DevTools and keep track-by rules tight as lists grow.</p>
</li>
</ul>
</div>
</div>
</div>
<]]></content:encoded>
					
		
		
			</item>
         
	<item>
		<title>Terminal-first Mouseless Development Or How To Be A Hipster Engineer</title>
		<link>https://blog.lunatech.com//posts/2025-07-11-terminal-first-mouseless-development-or-how-to-be-hipster-engineer</link>
		
		<dc:creator><![CDATA[]]></dc:creator>
        <pubDate>2025-07-11T00:00:00.000Z</pubDate>
         
             {
            <category><![CDATA[beyond-the-code]]></category>
                }
             {
            <category><![CDATA[bash-to-the-feature]]></category>
                }
             {
            <category><![CDATA[vim]]></category>
                }
             {
            <category><![CDATA[tmux]]></category>
                }
             {
            <category><![CDATA[cli]]></category>
                }
             {
            <category><![CDATA[terminal]]></category>
                }
             {
            <category><![CDATA[en]]></category>
                }
             {
            <category><![CDATA[en]]></category>
                }
             
        
		<guid isPermaLink="false">https://blog.lunatech.com//posts/2025-07-11-terminal-first-mouseless-development-or-how-to-be-hipster-engineer</guid>

					<description>
                        <![CDATA[ In this article, I'm going to give you a slightly different view on]]></description>
                    <content:encoded><![CDATA[
                    <div id="preamble">
<div class="sectionbody">
<div class="paragraph">
<p>In this article, I&#8217;m going to give you a slightly different view on
something you do on a daily basis. A philosophy that encourages you to
only use what you really need, keeps you away from being distracted,
lets you think about what your problem really involves, and trust what
your fingers have learned instead of relying on visual representation.
That is what I call terminal-first mouseless development. I&#8217;ll
try to sell it to you by giving an overview of how you can benefit from it in
real life. Apart from the theory,
we are also going to see real applications of these approaches.
In particular, we will talk about <code>tmux</code> and <code>neovim</code> — industry standards for becoming a real
hipster developer.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_hipster_development">Hipster development?</h2>
<div class="sectionbody">
<div class="paragraph">
<p>We are all familiar with our IDEs, coupled with other tools for
tasks like database management (DBeaver), testing APIs (Postman), and
container management (Docker Desktop). Even though they provide an
extensive GUI, they are also quite rich in distracting elements.
Additionally, using multiple tools and navigating between them
means a lot of context switching as well as having quite a loaded
environment. If you say that your favorite IDE has everything
built-in, then it violates the philosophy of Unix, which says that it is
more idiomatic to use small tools that do one thing well rather than the
opposite. Sort of a single responsibility principle.</p>
</div>
<div class="paragraph">
<p>And here comes what I call &#8220;<strong>Terminal-first development</strong>&#8221;, but it can be
called by any other similar terms. Its core principle is that your terminal
should be your central hub for development tasks.
Instead of installing a new GUI application to solve a problem, the terminal-first
approach challenges you to:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>Decompose the problem into smaller, distinct steps.</p>
</li>
<li>
<p>Assign a small, dedicated CLI tool to each step.</p>
</li>
<li>
<p>Combine these tools, piping their outputs together, to solve the initial challenge.</p>
</li>
</ul>
</div>
<div class="imageblock">
<div class="content">
<img src="../media/2025-07-11-terminal-first-mouseless-development-or-how-to-be-hipster-engineer/crazy-terminal.gif" alt="crazy terminal">
</div>
</div>
<div class="paragraph">
<p>As a practical example, you want to select an arbitrary table from your
database, get all of the data within it, and pretty-print it as JSON.
You have two options:</p>
</div>
<div class="olist arabic">
<ol class="arabic">
<li>
<p>Install and use a couple hundred megabytes of &#8220;pgAdmin&#8221; that
will create another distractive window in your workflow and eat your
memory, blasting your brain with all the buttons and menus around its
GUI.</p>
</li>
<li>
<p>Create a simple script that uses &#8220;psql&#8221; to get a list of all
tables in your database, pass them to &#8220;fzf&#8221; so you could interactively
select them, pass the table name again to &#8220;psql&#8221; to output data from it in
JSON, and finally pass it to &#8220;jq&#8221; to pretty-print the result.</p>
</li>
</ol>
</div>
<div class="paragraph">
<p>Even though I have already intentionally hated on option 1, there could
be a point like: &#8220;Why would I do everything said in point 2 if I
can just go to pgAdmin and press a single button or two?&#8221;. And that is
valid. And here we come to one of the most important points: the
approach described in option 2 is just an example of a philosophy that you
can follow or <strong>not</strong>. And that is your choice. And it would not be
incorrect or make you a bad developer. It is all about what you prefer
(and how lazy you are :P). But if you selected option 2, then you
probably prioritize:</p>
</div>
<div class="olist arabic">
<ol class="arabic">
<li>
<p>Modularity &amp; Portability</p>
</li>
<li>
<p>Better resource usage</p>
</li>
<li>
<p>Minimalistic &amp; distraction-free workflow</p>
</li>
<li>
<p>Scriptability &amp; Automation</p>
</li>
<li>
<p>Customisation</p>
</li>
</ol>
</div>
<div class="paragraph">
<p>Another interesting thing to think about the second approach is that if
you look closely, it is all about piping, or basically passing
data from one function to another. And with this approach, it gives you a
grounded look at something fundamental regarding software engineering in
general — it is quite a lot, if not completely, about viewing,
manipulating, and creating data. Actually, pretty much what our brains do.</p>
</div>
<div class="paragraph">
<p>Last but not least — such an approach really encourages learning,
deeper understanding, and mastering of general software engineering
skills, which eventually raises the level of craftsmanship. Personally,
this philosophy is what sparks joy in my everyday work.</p>
</div>
<div class="paragraph">
<p>Another philosophy that usually goes hand in hand with the terminal-first
one is mouseless or keyboard-centric development, which literally means
what it says — it encourages you to prioritize the usage of a keyboard
over a mouse or trackpad for writing or navigating through your code.
It is important to say here that it doesn’t mean that you should never use
those. Sometimes it is quite inefficient to avoid using your trackpad,
but for the most part, the theory is that mostly using your keyboard
makes your development faster, more efficient, and less tiring.</p>
</div>
<div class="imageblock">
<div class="content">
<img src="../media/2025-07-11-terminal-first-mouseless-development-or-how-to-be-hipster-engineer/monkey-smashing-mouse.gif" alt="monkey smashing mouse">
</div>
</div>
<div class="paragraph">
<p>Why? Well, you keep your hands on the keyboard and avoid switching
between it and a mouse. Additionally, you rely on muscle memory in the
form of keybindings and not on visual navigation to perform actions.
This way you reduce mental overhead, stay in the flow state, and perform basic
actions much faster. For example,
<a href="https://blog.superhuman.com/keyboard-vs-mouse/?utm_source=chatgpt.com">the
research by SuperHuman</a> showed that some basic operations that we
perform every day can be done from 2 to 5 seconds faster if performed
with a keyboard rather than a mouse. And we perform those actions a lot, so
think about the amount of time you could save in a day.</p>
</div>
<div class="paragraph">
<p>But let&#8217;s not idealize things and talk about the downsides. The primary one is a steep learning curve.
From my experience, following those philosophies really makes you
rethink the way you approach software development. I struggle to point
out the exact points, but it just feels quite different, and you really
need time to get used to that new reality, and that basically means a
long learning curve. The basic parts of it are memorizing all the
keybinds or switching your mindset to use CLIs over graphical applications. But
hey, learning all the buttons in your IDE also took time, so it is more
about whether you are ready to commit to that.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_core_in_practice">Core In Practice</h2>
<div class="sectionbody">
<div class="paragraph">
<p>So now, let’s finally go from something totally metaphorical to something
more practical. There isn&#8217;t a single right way to implement the philosophy that
I described above. But, while finding my own way there, I could
distinguish two core elements or, in fact, pieces of software, that will
help you to build up a foundation.</p>
</div>
<div class="sect2">
<h3 id="_tmux">tmux</h3>
<div class="paragraph">
<p>I mentioned that with terminal-first development, your terminal
becomes the &#8220;central hub&#8221; for solving software engineering tasks.
When you think about a hub, you probably expect it to provide an infrastructure
that you can utilize to effectively achieve your goals.
The industry standard for that is called &#8220;tmux&#8221;,
which is a terminal multiplexer by its definition.</p>
</div>
<div class="paragraph">
<p>It allows you to conveniently create terminal windows, splits, or even
sessions for grouping. That makes it easy to organize your work between
multiple projects, for example, and allows you to navigate more smoothly.</p>
</div>
<div class="paragraph">
<p>You can say, “Yeah, but my terminal emulator can do the same.” Sure, but
what if the keybinds change? What if you switch to another emulator? What if
you now have to use a different system? You basically need to adapt and
configure this new tool for yourself. So how does using &#8220;tmux&#8221; help you?
It is completely platform and terminal-emulator agnostic. Everything you have
to do is to put your configuration file in the root folder and run &#8220;tmux&#8221;.
This way you are completely independent of the platform that you run &#8220;tmux&#8221; on top of.</p>
</div>
<div class="imageblock">
<div class="content">
<img src="../media/2025-07-11-terminal-first-mouseless-development-or-how-to-be-hipster-engineer/tmux.png" alt="tmux">
</div>
</div>
<div class="paragraph">
<p>Another thing is that, at its core, &#8220;tmux&#8221; is a server, having all
your terminal sessions working in the background. So this can at least save
you from accidentally pressing Command + Q in your terminal and crashing
out again, but what you can also do is to basically have your whole
terminal session setup running, that you can SSH from any other machine
and have it all there, as &#8220;tmux&#8221; itself is just a command-line tool.
Combining a configuration basis and server nature, you basically become
independent of a machine and/or terminal emulation tools, if you have
your &#8220;tmux&#8221; server hosted somewhere.</p>
</div>
<div class="paragraph">
<p>Regarding the config, you can do quite a lot, starting from setting basic keybinds,
finishing with writing custom scripts for your workflow or modifying the UI.
There is even a whole ecosystem of plugins!</p>
</div>
<div class="paragraph">
<p>And if we talk about downsides, there are not that many, except
for the steep learning curve, but trust me, the outcome is worth it.</p>
</div>
</div>
<div class="sect2">
<h3 id="_neovim">neovim</h3>
<div class="paragraph">
<p>I think most of you know &#8220;vi&#8221; — the editor that&#8217;s impossible to exit. One of the
first text editors in existence, it relies on the keyboard only.
This is because there was no mouse in the early computer days. Theoretically, you can use
it to perform any tasks related to text editing and code writing. But
the problem with the original &#8220;vi&#8221; is that it is as plain as possible,
and when it comes to modern development, not really efficient. For
example, not having the ability to autocomplete code or quickly navigate to
a class definition doesn’t sound like a lot of productivity.</p>
</div>
<div class="paragraph">
<p>To solve this issue, &#8220;vim&#8221; was created — a feature-rich version of
the original &#8220;vi&#8221; with things like syntax highlighting, the ability to split
windows, etc. And most importantly — it provides the ability for extensive
configuration, even featuring its own language — &#8220;vimscript&#8221;. That
basically created the possibility to write plugins that allow you to
customize your experience in &#8220;vim&#8221; however you want. As a result,
the &#8220;vim&#8221; plugin ecosystem is probably one of the biggest plugin
ecosystems in the world.</p>
</div>
<div class="paragraph">
<p>But this was not enough for people who considered themselves to be ultra-hipsters.
This led to the creation of &#8220;Neovim&#8221; - a fork, partly rewritten in Lua.
This way, significant gains were achieved in terms of extensibility and architecture.
Nowadays, &#8220;Neovim&#8221; is known for its great documentation and is supported by a quite big and active community of contributors.</p>
</div>
<div class="paragraph">
<p>Ultimately, you can think of &#8220;*vim&#8221; as a constructor.
Its ecosystem provides you with the bricks you can use to build a development
tool to satisfy any of your needs. From the most plain text editor to
an ultra-feature-rich IDE. Basically, you can completely replace whatever you are using now.
Just watch out so as not to violate the Unix philosophy.</p>
</div>
<div class="paragraph">
<p>So how does switching to &#8220;*vim&#8221; feel, and what does it bring to your
life? First of all, text editing starts to feel so much smoother, and the
whole navigation process around the code feels really fluent. Using
&#8220;*vim&#8221; really proves the benefits of trusting your muscle memory via
keybinds instead of visual navigating. The overall overhead goes down,
and you can also feel it when you have to work with several
projects/directories. Opening a project, quickly looking for something,
and editing it feels so light and easy. Using &#8220;*vim&#8221; is like dropping
a huge backpack when going uphill and changing it for something small,
compact, accessible, but extendable at the same time. And last but not
least, making the editor behave literally however you want it to in
a programmatic way is another amazing part.</p>
</div>
<div class="imageblock">
<div class="content">
<img src="../media/2025-07-11-terminal-first-mouseless-development-or-how-to-be-hipster-engineer/nvim.png" alt="nvim">
</div>
</div>
<div class="paragraph">
<p>But let’s not forget about the struggles you may face: &#8220;*vim&#8221; really makes
you rethink the way you write your code (and using keybinds is not the
only part), which will take quite some time. Another thing is
configuring the thing to meet your needs. Yeah, that takes time.
Initially, it took me maybe like 20+ hours, and it is also a non-stop
process, but that is a fair trade-off for the extensibility you get. There
is a joke in the &#8220;*vim&#8221; community about people spending more time on customizing
their config than on actually using it. And another thing is
that as it is community-driven, you may face things that don’t work
properly. For example, in order to have all the IDE features for Java,
you need to run Eclipse’s &#8220;jdtls&#8221;, a language server,
which doesn&#8217;t usually perform well on a large Java codebase.
But your mileage may vary.</p>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_conclusions">Conclusions</h2>
<div class="sectionbody">
<div class="paragraph">
<p>My main point in this article was to provide you with a new perspective.
An approach that you can incorporate in your day-to-day tasks.
A philosophy that embraces you to:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>Think more about what your task involves and what you really need to solve it</p>
</li>
<li>
<p>Maintain your workspace clean and distraction-free</p>
</li>
<li>
<p>Build a unique environment that you love working in</p>
</li>
<li>
<p>Introduce joy and creativity into your routine</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>And while it might feel like a step back, this philosophy is surprisingly forward-thinking.
Many of today&#8217;s brand-new AI tools are designed specifically for the command line.
In the end, there is no single way to do things.
Technical benefits like efficiency are important, but so is finding joy and pride in your craft.
Hipster engineering is something that makes me a better professional and makes me love what I do.
My sincere hope is that you find your own way to do the same.
Thanks for reading.</p>
</div>
<div class="imageblock">
<div class="content">
<img src="../media/2025-07-11-terminal-first-mouseless-development-or-how-to-be-hipster-engineer/dancing-puppy.gif" alt="dancing puppy">
</div>
</div>
</div>
</div>
<]]></content:encoded>
					
		
		
			</item>
         
	<item>
		<title>Ctrl+Alt+Defeat: Noob vs. Neural Net</title>
		<link>https://blog.lunatech.com//posts/2025-07-04-ctrl-alt-defeat</link>
		
		<dc:creator><![CDATA[]]></dc:creator>
        <pubDate>2025-07-04T00:00:00.000Z</pubDate>
         
             {
            <category><![CDATA[beyond-the-code]]></category>
                }
             {
            <category><![CDATA[bash-to-the-feature]]></category>
                }
             {
            <category><![CDATA[AI]]></category>
                }
             {
            <category><![CDATA[neural network]]></category>
                }
             {
            <category><![CDATA[en]]></category>
                }
             
        
		<guid isPermaLink="false">https://blog.lunatech.com//posts/2025-07-04-ctrl-alt-defeat</guid>

					<description>
                        <![CDATA[ For decades, competitive games have served as milestones in artificial intelligence research. From IBM’s Deep Blue beating Garry Kasparov at chess in 1997, to AlphaGo’s victory over Lee Sedol in 2016, games have offered a clear stage for AI to measure itself against the best human minds.]]></description>
                    <content:encoded><![CDATA[
                    <div id="preamble">
<div class="sectionbody">
<div class="paragraph">
<p>For decades, competitive games have served as milestones in artificial intelligence research. From IBM’s Deep Blue beating Garry Kasparov at chess in 1997, to AlphaGo’s victory over Lee Sedol in 2016, games have offered a clear stage for AI to measure itself against the best human minds.</p>
</div>
<div class="paragraph">
<p>But as games have grown more complex, so too has the challenge. Turn-based board games like chess and Go, while difficult, offer complete information and relatively limited options per move. Real-time strategy games like StarCraft II and Dota 2, however, introduce chaos: thousands of actions per minute, imperfect information, shifting alliances, and the need for long-term planning — all in real time.</p>
</div>
<div class="paragraph">
<p>So the question arises: Can AI beat humans in these games, fairly, without relying on superhuman speed or godlike awareness? Let’s take a deeper look into how two landmark systems, OpenAI Five and AlphaStar, set out to do just that.<br></p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_the_complexity_of_real_time_strategy_games">The Complexity of Real-Time Strategy Games</h2>
<div class="sectionbody">
<div class="paragraph">
<p>To appreciate the achievements of AI in games like Dota 2 and StarCraft II, it&#8217;s essential to understand what makes these games hard:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>Partial information: Players don’t see the whole map due to fog of war.<br></p>
</li>
<li>
<p>High action complexity: At any moment, there are thousands of possible moves.<br></p>
</li>
<li>
<p>Real-time dynamics: No turns, decisions must be made continuously.<br></p>
</li>
<li>
<p>Coordination: Especially in team games, success hinges on synergy and communication.<br></p>
</li>
<li>
<p>Long-term planning: Decisions made in the early game can determine the late-game outcome.<br></p>
</li>
</ul>
</div>
<div class="paragraph">
<p>Unlike games with set openings and established endgames, these environments are closer to the messiness of the real world and that’s exactly why they interest AI researchers.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_openai_five_dota_2_without_superpowers">OpenAI Five: Dota 2 Without Superpowers</h2>
<div class="sectionbody">
<div class="paragraph">
<p>In 2019, OpenAI introduced OpenAI Five, a team of five neural networks trained to play Dota 2, a popular and highly complex team-based multiplayer game. Unlike previous AIs, OpenAI Five didn’t rely on hardcoded rules. Instead, it learned by playing itself millions of times in a massive distributed training setup.</p>
</div>
<div class="paragraph">
<p>What made OpenAI Five especially impressive was the effort to simulate human-like constraints:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>Reaction time was capped at 200 milliseconds, close to average human reflexes.<br></p>
</li>
<li>
<p>Actions per minute (APM) were restricted to human levels, avoiding the inhuman speed advantage.<br></p>
</li>
<li>
<p>It had no access to information unavailable to humans, like opponent positions under fog of war.<br></p>
</li>
</ul>
</div>
<div class="paragraph">
<p>Despite these constraints, OpenAI Five steadily improved and eventually beat top human teams culminating in a 2–0 victory over the reigning world champion team OG at The International in 2019.</p>
</div>
<div class="paragraph">
<p>Yet, Five was not without flaws. It was:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>Weaker in novel situations it hadn’t seen during training.<br></p>
</li>
<li>
<p>Sometimes inflexible, making odd decisions when opponents deviated from expected tactics.<br></p>
</li>
<li>
<p>Emotionally agnostic, meaning while it would never play emotionally, it also doesn’t have the ability to read human psychology or use momentum the way humans do.<br></p>
</li>
</ul>
</div>
<div class="paragraph">
<p>Still, the fact that an AI could beat the world’s best without using non-human like reactions speeds speaks for itself.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_alphastar_outmaneuvering_pros_in_starcraft_ii">AlphaStar: Outmaneuvering Pros in StarCraft II</h2>
<div class="sectionbody">
<div class="paragraph">
<p>DeepMind’s AlphaStar tackled StarCraft II, another legendary RTS known for its brutal learning curve and mechanical demands. It used a combination of imitation learning (watching human games) and self-play reinforcement learning to master the game.</p>
</div>
<div class="paragraph">
<p>Like OpenAI Five, AlphaStar imposed human-like limitations:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>Capped APM and reaction delays (averaging around 350 milliseconds).<br></p>
</li>
<li>
<p>Camera view limitations, meaning it had to "look" around the map like a human player.<br></p>
</li>
<li>
<p>Trained against a diversity of opponents and strategies.<br></p>
</li>
</ul>
</div>
<div class="paragraph">
<p>AlphaStar climbed the European ladder to Grandmaster, ranking in the top 0.2% of players. It beat professional players like TLO and MaNa convincingly, sometimes using unexpected and creative strategies.</p>
</div>
<div class="paragraph">
<p>However, it too had its shortcomings:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>Predictability: Once players had time to study it, some human pros found exploitable patterns.<br></p>
</li>
<li>
<p>Lack of intuitive game sense: Humans often make intuitive calls based on experience, psychology, or a “feel” for the flow of the game — AlphaStar relied solely on data and outcomes.<br></p>
</li>
<li>
<p>Difficulty adapting to “meta shifts”, since it lacked the kind of quick generalization humans can make from limited examples.<br></p>
</li>
</ul>
</div>
<div class="paragraph">
<p>Even so, AlphaStar showed that AI could compete — and win — not by outclicking, but by outthinking.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_summary_of_the_restrictions_imposed_on_the_ais">Summary of the restrictions imposed on the AI&#8217;s</h2>
<div class="sectionbody">
<table class="tableblock frame-all grid-all stretch">
<colgroup>
<col style="width: 25%;">
<col style="width: 25%;">
<col style="width: 25%;">
<col style="width: 25%;">
</colgroup>
<thead>
<tr>
<th class="tableblock halign-left valign-top">Metric</th>
<th class="tableblock halign-left valign-top">Pro Human Player</th>
<th class="tableblock halign-left valign-top">OpenAI Five</th>
<th class="tableblock halign-left valign-top">AlphaStar</th>
</tr>
</thead>
<tbody>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">Average Reaction Time</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">~200 ms</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">200 ms</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">350 ms</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">Max APM</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">~300</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">~180</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">~150</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">Map Vision</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Partial</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Partial</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Limited camera view</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">Strategy Adaptation</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">High</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Medium</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Medium-High</p></td>
</tr>
</tbody>
</table>
</div>
</div>
<div class="sect1">
<h2 id="_where_ai_still_falls_short">Where AI Still Falls Short</h2>
<div class="sectionbody">
<div class="paragraph">
<p>Even with these victories, AI is not yet a complete replacement for human intelligence in games. Some weaknesses include:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>Lack of common sense or intuition: AIs still struggle with decisions that require real-world reasoning or emotional awareness.<br></p>
</li>
<li>
<p>Context blindness: Without extensive training, AIs can’t generalize well to new game versions or unexpected strategies.<br></p>
</li>
<li>
<p>Communication and deception: While some advanced AIs, like Meta&#8217;s "CICERO", have made progress in games that involve negotiation and persuasion — such as the board game Diplomacy — most game-playing AIs still struggle to understand or influence human opponents the way skilled players can. They can&#8217;t read body language, sense bluffing, or adapt their strategy based on trust or psychology — key elements of human gameplay.<br></p>
</li>
<li>
<p>Creativity with purpose: AIs can discover new tactics, but they don’t “understand” them in a human sense, nor can they justify them conceptually.<br></p>
</li>
</ul>
</div>
<div class="paragraph">
<p>In essence, AI can win — but it doesn&#8217;t always know why it wins.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_conclusion_a_new_era_of_competitive_play">Conclusion: A New Era of Competitive Play</h2>
<div class="sectionbody">
<div class="paragraph">
<p>So, can AI truly outplay humans at complex games? The answer, remarkably, is yes — even under constraints that mimic human limitations. OpenAI Five and AlphaStar both demonstrated that intelligent agents can excel in games long thought too complex for machines.</p>
</div>
<div class="paragraph">
<p>But while the victories are real, the limitations are too. These AIs don’t think or feel like us. They win through scale, training, and narrow focus — not general intelligence or intuition.</p>
</div>
<div class="paragraph">
<p>Still, each success in these arenas nudges us closer to AI that can not only perform, but reason, adapt, and collaborate — skills that matter far beyond the game board.</p>
</div>
</div>
</div>
<]]></content:encoded>
					
		
		
			</item>
         
	<item>
		<title>GPU Programming For The Brave</title>
		<link>https://blog.lunatech.com//posts/2025-06-27-gpu-programming-for-the-brave</link>
		
		<dc:creator><![CDATA[Boyuan Xiao]]></dc:creator>
        <pubDate>2025-06-27T00:00:00.000Z</pubDate>
         
             {
            <category><![CDATA[beyond-the-code]]></category>
                }
             {
            <category><![CDATA[bash-to-the-feature]]></category>
                }
             {
            <category><![CDATA[GPU programming]]></category>
                }
             {
            <category><![CDATA[CUDA]]></category>
                }
             {
            <category><![CDATA[parallel programming]]></category>
                }
             {
            <category><![CDATA[AI]]></category>
                }
             {
            <category><![CDATA[neural network]]></category>
                }
             {
            <category><![CDATA[en]]></category>
                }
             
        
		<guid isPermaLink="false">https://blog.lunatech.com//posts/2025-06-27-gpu-programming-for-the-brave</guid>

					<description>
                        <![CDATA[ GPUs, some might call them graphic cards, have never been a stranger for video gamers. The evolution of GPUs significantly changed not just the video game industry, but also the field of parallel programming.]]></description>
                    <content:encoded><![CDATA[
                    <div class="sect1">
<h2 id="_introduction">Introduction</h2>
<div class="sectionbody">
<div class="paragraph">
<p>GPUs, some might call them graphic cards, have never been a stranger for video gamers. The evolution of GPUs significantly changed not just the video game industry, but also the field of parallel programming.</p>
</div>
<div class="paragraph">
<p>I was lucky enough to participate some courses that briefly introduced GPU programming during my master study. As my first humble attempt, I hereby write down my knowledge and understanding about GPU programming in this blog post. Hopefully, after reading this write-up, you can have a basic idea about: how GPUs work, how to do some simple GPU programming and why it is so important to the field of AI.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_what_is_gpu">What is GPU</h2>
<div class="sectionbody">
<div class="paragraph">
<p>GPU is the abbreviation of "graphics processing unit". It is a specialized electronic circuit designed for digital image processing and to accelerate computer graphics, being present either as a discrete video card or embedded on motherboards, mobile phones, personal computers, workstations, and game consoles.</p>
</div>
<div class="paragraph">
<p>If you have tried to build your own PC, you will probably call the big gas-stove-look-a-like thing in <a href="#card">Figure 1</a> a GPU. However, this is not entirely correct. Graphics card is a more suitable name for it. And if you have ever had a chance to disassemble a graphics card like me, then I am sure you will notice there are much more than just a GPU on a graphics card. The GPU itself is only a small part on it and there&#8217;s memory, power supply and cooling unit. The composition resembles any normal PC you can see. <a href="#disassembled-card">Figure 2</a> is taken when I had an GPU memory overheating issue. As you can see in the picture, the GPU is surrounded by the red box and blue boxes for the GPU memory. The part on the right is the cooling unit.</p>
</div>
<div class="openblock float-group">
<div class="content">
<div id="card" class="imageblock left">
<div class="content">
<img src="../media/2025-06-27-gpu-programming-for-the-brave/my_graphics_card_2.png" alt="A" width="800">
</div>
<div class="title">Figure 1. My Nvidia RTX 3080.</div>
</div>
<div id="disassembled-card" class="imageblock right">
<div class="content">
<img src="../media/2025-06-27-gpu-programming-for-the-brave/my_graphics_card_1.png" alt="B" width="800">
</div>
<div class="title">Figure 2. My Nvidia RTX 3080 (disassemble).</div>
</div>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_the_small_exercise">The small exercise</h2>
<div class="sectionbody">
<div class="paragraph">
<p>There is no way we can actually know how to do GPU programming by just looking at the composition picture. To help with the understanding, let&#8217;s consider a small code exercise where you have to implement a simple <code>fill_matrix</code> function in C to fill a rectangle shape within a two-dimensional matrix with some certain value:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-c" data-lang="c">#include &lt;stdio.h&gt;
#include &lt;stdlib.h&gt;

void fill_matrix(int **s, int x_len, int y_len, int draw_start, int draw_end, int value_to_fill) {
  // IMPLEMENT ME
}

void print_matrix(int **s, int x_len, int y_len) {
  // doesn't matter...
}

int64_t initialize_matrix(int rows, int cols) {
  // doesn't matter...
}

int main() {
  int **s = (int **)initialize_matrix(10, 10);
  printf("before: \n");
  print_matrix(s, 10, 10);

  fill_matrix(s, 10, 10, 2, 8 9);

  printf("after: \n");
  print_matrix(s, 10, 10);
  return 0;
}</code></pre>
</div>
</div>
<div class="sect2">
<h3 id="_c_version">C version</h3>
<div class="paragraph">
<p>Easy, isn&#8217;t it? All we need to do is to use two nested for-loops to fill the value when the loop arrives the expected range:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-c" data-lang="c">void fill_matrix(int **s, int x_len, int y_len, int draw_start, int draw_end, int value_to_fill) {
  for (int i = 0; i &lt; y_len; i++) {
    for (int j = 0; j &lt; x_len; j++) {
      if (i &gt; draw_start &amp;&amp; i &lt; draw_end &amp;&amp; j &gt; draw_start &amp;&amp; j &lt; draw_end) {
        s[i][j] = value_to_fill;
      }
    }
  }
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>If you would like to speed up your implementation, you can even use <a href="https://www.openmp.org/">OpenMp</a> to turn your it into a multi-threaded implementation by simply adding <code>#pragma omp parallel for collapse(2)</code> on top of the outer for-loop. After re-compiling and running <code>export OMP_NUM_THREADS=4</code>, your program should automatically delegate the execution of the for-loop to at most 4 threads.</p>
</div>
<div class="paragraph">
<p>Now it seems like we really pushed to the boundary, and couldn&#8217;t get any more speedup unless increasing the number of threads. However, what we have seen so far is still in the realm of CPU programming, where your code gets executed by the CPU. Besides that, the time complexity of the implementation is <code>O(n*m)</code>, which is not a very pleasant number. So let&#8217;s try to make use of the power of GPUs, with which we could achieve O(1) complexity.</p>
</div>
</div>
<div class="sect2">
<h3 id="_cuda_version">CUDA version</h3>
<div class="admonitionblock tip">
<table>
<tr>
<td class="icon">
<div class="title">Tip</div>
</td>
<td class="content">
<div class="paragraph">
<p>You might find it helpful to temporarily forget what you have learnt about <code>thread</code> and <code>kernel</code> when reading this section.</p>
</div>
</td>
</tr>
</table>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-c" data-lang="c">__global__ void fill_matrix_kernel(int* matrix, int rows, int cols, int draw_start, int draw_end, int value) {
    int row = blockIdx.y * blockDim.y + threadIdx.y;
    int col = blockIdx.x * blockDim.x + threadIdx.x;

    if (row &gt; draw_start &amp;&amp; row &lt; draw_end &amp;&amp; col &lt; draw_end &amp;&amp; col &gt; draw_start) {
        int idx = row * cols + col;
        matrix[idx] = value;
    }
}

int main() {
  const int rows = 10;
  const int cols = 10;
  const size_t size = rows * cols * sizeof(int);

  // Host memory
  int* h_matrix = (int *)malloc(size);

  // Device memory
  int* d_matrix;
  cudaMalloc((void **)&amp;d_matrix, size);

  // Define grid and block dimensions
  dim3 block(32, 32);  // 256 threads per block
  dim3 grid(
      (cols + block.x - 1) / block.x,  // ceil(cols/block.x)
      (rows + block.y - 1) / block.y   // ceil(rows/block.y)
  );

  // Launch kernel
  fill_matrix_kernel&lt;&lt;&lt;grid, block&gt;&gt;&gt;(d_matrix, rows, cols, 2, 8 9);

  // Copy result back to host
  cudaMemcpy(h_matrix, d_matrix, size, cudaMemcpyDeviceToHost);

  // Verify values
  print_matrix(h_matrix, rows, cols);

  // Cleanup
  free(h_matrix);
  cudaFree(d_matrix);

  return 0;
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>Above is the CUDA implementation. CUDA is a C-like programming language provided by Nvidia. Naturally, it only runs on Nvidia cards. To compile the code above, we can simply run <code>nvcc -o code_example code_example.cu</code> just like when compiling C code using <code>gcc</code>. Then, the <code>code_example</code> it produces also isn&#8217;t any different from other native executable, which could be run by the command <code>./code_example</code>.</p>
</div>
<div class="paragraph">
<p>So what happens when we run it? Besides allocating memory on the device, which is our graphics card, the computation kernel (the <code>fill_matrix_kernel</code> function) is executed by all the GPU threads that we requested simultaneously. In the example, we define a grid of one block ((10 + 32 - 1) / 32 = 1) with 256 threads on it. GPU threads are fundamentally different from the CPU threads we know. By design, the number of GPU threads on a GPU is much larger than the number of CPU threads on a CPU. On top of that, what is executed by CPU threads is completely dependent on how you program it. On contrast, GPU threads provides high-throughput due to the nature of simultaneous execution for a kernel. Therefore, we need a way to control the behavior of each GPU thread. Luckily, an unique <code>threadId</code> is assigned to each GPU thread within the same block and each block has a unique <code>blockId</code>. What we can do is to see if the the current thread is within the drawing range and fill the value accordingly based on the location of the thread (<code>blockId</code> * <code>number of blocks</code> + <code>threadId</code>) , which is exactly what the <code>if</code> clause is doing.</p>
</div>
<div class="openblock float-group">
<div class="content">
<div class="imageblock left">
<div class="content">
<img src="../media/2025-06-27-gpu-programming-for-the-brave/gpu_architecture_1.png" alt="A" width="480">
</div>
<div class="title">Figure 3. The Grid, The Block and The Thread.</div>
</div>
<div class="imageblock right">
<div class="content">
<img src="../media/2025-06-27-gpu-programming-for-the-brave/gpu_architecture_2.png" alt="B" width="800">
</div>
<div class="title">Figure 4. Nvidia&#8217;s interpretation.</div>
</div>
</div>
</div>
<div class="paragraph">
<p>If we leave out the <code>main()</code> function, the actual implementation is only 6 lines and there is no loop being used at all. But how much faster it really is? When running with the matrix shape of 32768 * 32768, our CUDA implementation can finish it within 0.3 seconds while the C implementation needs 1.9 seconds.</p>
</div>
<div class="openblock float-group">
<div class="content">
<div class="imageblock text-center">
<div class="content">
<img src="../media/2025-06-27-gpu-programming-for-the-brave/speed_result.png" alt="Speed showcase." width="800">
</div>
<div class="title">Figure 5. Speed showcase.</div>
</div>
</div>
</div>
<div class="paragraph">
<p>Impressive, isn&#8217;t it? But trust me, everything seems reasonable when you actually see the difference of thread numbers:</p>
</div>
<table class="tableblock frame-all grid-all stretch">
<colgroup>
<col style="width: 33.3333%;">
<col style="width: 33.3333%;">
<col style="width: 33.3334%;">
</colgroup>
<thead>
<tr>
<th class="tableblock halign-left valign-top"><a href="https://www.intel.com/content/www/us/en/products/sku/240782/intel-xeon-6966pc-processor-432m-cache-3-00-ghz/specifications.html">Intel® Xeon® 6966P-C Processor</a></th>
<th class="tableblock halign-left valign-top"><a href="https://www.amd.com/en/products/processors/workstations/ryzen-threadripper.html#specifications">AMD Ryzen Threadripper PRO 9995WX</a></th>
<th class="tableblock halign-left valign-top"><a href="https://www.nvidia.com/en-us/geforce/graphics-cards/50-series/rtx-5090/">Nvidia RTX 5090</a></th>
</tr>
</thead>
<tbody>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">192 threads in total</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">192 threads in total</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">21760 CUDA threads</p></td>
</tr>
</tbody>
</table>
<div class="admonitionblock tip">
<table>
<tr>
<td class="icon">
<div class="title">Tip</div>
</td>
<td class="content">
<div class="paragraph">
<p>This code example might be too simple and too boring for you. But if you think of the matrix that we are filling as a screen, and the value as RGB value&#8201;&#8212;&#8201;We are actually rendering a screen!</p>
</div>
</td>
</tr>
</table>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_okay_but_why_ai">Okay, but why AI?</h2>
<div class="sectionbody">
<div class="paragraph">
<p>As you might have heard, GPUs are widely used in the field of AI. Given the high-throughput trait of GPU, the process of AI model training can be significantly facilitated. But why is that?</p>
</div>
<div class="sect2">
<h3 id="_look_into_the_ai">Look into the AI</h3>
<div class="paragraph">
<p>Thankfully, Wikipedia made it a lot easier for me to explain AI:</p>
</div>
<div class="literalblock">
<div class="content">
<pre>"The largest and most capable LLMs are generative pretrained transformers (GPTs), which are largely used in generative chatbots such as ChatGPT or Gemini."</pre>
</div>
</div>
<div class="literalblock">
<div class="content">
<pre>"A GPT is a type of LLM and a prominent framework for generative artificial intelligence. It is an artificial neural network that is used in natural language processing by machines.".</pre>
</div>
</div>
<div class="paragraph">
<p>To put it simply: <strong>most of the popular AIs are made of neural networks.</strong> A neural network is composite of multiple layers of nodes. The first layer takes input from the outside world, normally as the format of a vector of numbers. The output of a layer consists of the output number from each node, which is calculated by summing the input times the weight of the node (sum(input * weight)). And all the subsequent layers take input from the previous one. The process of training the neural network aims to find the weights for each nodes so that the output is most acceptable. And it requires to feed the input &#8594; calculate the output &#8594; compare with the expected output &#8594; adjust the weights repetitively.</p>
</div>
<div class="openblock float-group">
<div class="content">
<div class="imageblock text-center">
<div class="content">
<img src="../media/2025-06-27-gpu-programming-for-the-brave/neural_network.png" alt="Speed showcase." width="800">
</div>
<div class="title">Figure 6. A neural network.</div>
</div>
</div>
</div>
</div>
<div class="sect2">
<h3 id="_we_can_let_gpu_run_this">We can let GPU run this</h3>
<div class="paragraph">
<p>If we try to write a simple implementation, or even pseudo code, of how things are done in each layer of a neural network, we could arrive at what is shown in <a href="#c-implementation">Figure 7</a>. Once again we see a pattern we have seen just before: a linear algebra calculation wrapped by two for-loops. Therefore, we can easily rewrite to a CUDA implementation shown in <a href="#cuda-implementation">Figure 8</a>.</p>
</div>
<div class="openblock float-group">
<div class="content">
<div id="c-implementation" class="imageblock left">
<div class="content">
<img src="../media/2025-06-27-gpu-programming-for-the-brave/neural_network_layer_c.png" alt="Speed showcase." width="600">
</div>
<div class="title">Figure 7. C implementation of a neural network layer.</div>
</div>
<div id="cuda-implementation" class="imageblock right">
<div class="content">
<img src="../media/2025-06-27-gpu-programming-for-the-brave/neural_network_layer_cuda.png" alt="Speed showcase." width="900">
</div>
<div class="title">Figure 8. CUDA implementation of a neural network layer.</div>
</div>
</div>
</div>
<div class="paragraph">
<p>Both <a href="#c-implementation">Figure 7</a> and <a href="#cuda-implementation">Figure 8</a> are taken from a research article by Ricardo Brito et al[<a href="#1">[1]</a>]. The authors managed to utilize the high-throughput of GPU to accelerate the training process of a neural network in the year of 2016. Except for the countless open-source repositories that implement CUDA-based neural networks, Nvidia offers <a href="https://developer.nvidia.com/cudnn#">cuDNN</a> as a GPU-accelerated library of primitives for deep neural networks. Popular neural network frameworks like <a href="https://pytorch.org/get-started/locally/">PyTorch</a> and <a href="https://www.tensorflow.org/guide/gpu">TenhsorFlow</a> can operate on GPU devices without any extra effort.</p>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_to_sum_up">To sum up</h2>
<div class="sectionbody">
<div class="paragraph">
<p>GPUs, which are originally made for graphics processing, has shown a huge potential in the field of parallel programming and AI training due to their high-throughput nature. This is achieved by piling significant amount of GPU threads and impose simultaneous execution of the compute kernel. Even though it&#8217;s not quite possible to assign GPU threads for different execution routine like CPU threads, we can still do minimum control-flow manipulation based on their <code>threadId</code>. Several examples of CUDA, which is a C-like GPU programming language offered by Nvidia, are also shown to demonstrate its syntax.</p>
</div>
<div class="paragraph">
<p>Finally, you can checkout the code examples I used in <a href="https://github.com/555isfaiz/gpu_programming_example">this GitHub repo</a>.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_references">References</h2>
<div class="sectionbody">
<div class="ulist bibliography">
<ul class="bibliography">
<li>
<p>[[[1]]] Brito R., Fong S., Cho K., Song W., Wong R., Mohammed S., Fiaidhi J.
"GPU-enabled back-propagation artificial neural network for digit recognition in parallel".
<em>The Journal of Supercomputing</em>. 72, (2016).
<a href="https://doi.org/10.1007/s11227-016-1633-y" class="bare">https://doi.org/10.1007/s11227-016-1633-y</a></p>
</li>
</ul>
</div>
</div>
</div>
<]]></content:encoded>
					
		
		
			</item>
         
	<item>
		<title>Graveyard of technologies</title>
		<link>https://blog.lunatech.com//posts/2025-06-20-graveyard-of-technologies</link>
		
		<dc:creator><![CDATA[Pere Tarrida]]></dc:creator>
        <pubDate>2025-06-20T00:00:00.000Z</pubDate>
         
             {
            <category><![CDATA[beyond-the-code]]></category>
                }
             {
            <category><![CDATA[bash-to-the-feature]]></category>
                }
             {
            <category><![CDATA[ALGOL]]></category>
                }
             {
            <category><![CDATA[Japronto]]></category>
                }
             {
            <category><![CDATA[Apache Ant]]></category>
                }
             {
            <category><![CDATA[Windows Phone]]></category>
                }
             {
            <category><![CDATA[Google Glass]]></category>
                }
             {
            <category><![CDATA[Microsoft Zune]]></category>
                }
             {
            <category><![CDATA[Netscape Navigator]]></category>
                }
             {
            <category><![CDATA[Adobe Flash]]></category>
                }
             {
            <category><![CDATA[Visual Basic]]></category>
                }
             {
            <category><![CDATA[Fortran]]></category>
                }
             {
            <category><![CDATA[Smalltalk]]></category>
                }
             {
            <category><![CDATA[Technology Adoption]]></category>
                }
             {
            <category><![CDATA[Market Failure]]></category>
                }
             {
            <category><![CDATA[Software History]]></category>
                }
             {
            <category><![CDATA[Hardware History]]></category>
                }
             {
            <category><![CDATA[Ecosystem Strategy]]></category>
                }
             {
            <category><![CDATA[Innovation vs. Viability]]></category>
                }
             {
            <category><![CDATA[Legacy Technology]]></category>
                }
             {
            <category><![CDATA[Product Lifecycle]]></category>
                }
             {
            <category><![CDATA[Developer Experience]]></category>
                }
             {
            <category><![CDATA[User Adoption]]></category>
                }
             {
            <category><![CDATA[en]]></category>
                }
             
        
		<guid isPermaLink="false">https://blog.lunatech.com//posts/2025-06-20-graveyard-of-technologies</guid>

					<description>
                        <![CDATA[ ALGOL, Japronto, and Apache Ant represent fascinating case studies of software that, despite their technical merits, faced significant challenges in achieving lasting market success. Each offers valuable lessons about the complex relationship between technical excellence and commercial viability.]]></description>
                    <content:encoded><![CDATA[
                    <div class="sect1">
<h2 id="_software_when_technical_excellence_isnt_enough">Software: When Technical Excellence Isn&#8217;t Enough</h2>
<div class="sectionbody">
<div class="paragraph">
<p>ALGOL, Japronto, and Apache Ant represent fascinating case studies of software that, despite their technical merits, faced significant challenges in achieving lasting market success. Each offers valuable lessons about the complex relationship between technical excellence and commercial viability.
 ALGOL, Japronto, and Apache Ant: Lessons in Technology Adoption</p>
</div>
<div class="paragraph">
<p>Represent fascinating case studies of technologies that, despite their technical merits, faced significant challenges in achieving lasting market success. Each offers valuable lessons about the complex relationship between technical excellence and commercial viability.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_algol_revolutionary_syntax_that_shaped_programming">ALGOL: Revolutionary Syntax That Shaped Programming</h2>
<div class="sectionbody">
<div class="paragraph">
<p>ALGOL introduced groundbreaking programming concepts that influenced virtually every modern programming language. The language featured elegant recursive procedures and call-by-name parameters, as demonstrated in this classic example:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-algol" data-lang="algol">real procedure GPS (I, N, Z, V); integer I; real N, Z, V;
begin
   for I := 1 step 1 until N do
      Z := V;
   GPS := 1;
end;</code></pre>
</div>
</div>
<div class="paragraph">
<p>This GPS (General Problem Solver) procedure showcased ALGOL&#8217;s sophisticated parameter passing mechanisms and recursive capabilities. The language&#8217;s clean syntax and mathematical precision made it ideal for academic research and algorithm description. ALGOL&#8217;s influence can be seen in modern languages through its introduction of block structure, lexical scoping, and formal syntax definition using Backus-Naur Form.</p>
</div>
<div class="paragraph">
<p>However, ALGOL&#8217;s academic origins became its commercial weakness. The language prioritized theoretical elegance over practical business applications, creating a barrier for commercial adoption. Unlike FORTRAN, which had IBM&#8217;s backing and clear scientific computing applications, ALGOL remained primarily an academic exercise without strong industry support.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_japronto_the_performance_paradox">Japronto: The Performance Paradox</h2>
<div class="sectionbody">
<div class="paragraph">
<p>Japronto emerged as a high-performance Python HTTP framework, promising extraordinary speed through aggressive optimization. A typical Japronto application demonstrated its streamlined approach:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-python" data-lang="python">from japronto import Application

def hello(request):
    return request.Response(text='Hello world!')

app = Application()
app.router.add_route('/', hello)
app.run(debug=True)</code></pre>
</div>
</div>
<div class="paragraph">
<p>The framework achieved remarkable performance by optimizing HTTP pipelining and utilizing the picohttpparser C library with SSE4.2 CPU instructions. Japronto could handle over 1 million requests per second in benchmarks, dramatically outperforming traditional Python frameworks and even some Go alternatives.</p>
</div>
<div class="paragraph">
<p>However, this performance came at a significant cost. Japronto&#8217;s speed optimizations discouraged the use of Python-level objects and complex application logic. The framework relied heavily on HTTP pipelining, which modern browsers don&#8217;t support reliably. Most critically, real-world applications requiring database connections, business logic, and data processing couldn&#8217;t maintain Japronto&#8217;s benchmark performance levels.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_apache_ant_the_xml_build_tool_era">Apache Ant: The XML Build Tool Era</h2>
<div class="sectionbody">
<div class="paragraph">
<p>Apache Ant dominated Java build automation for years with its XML-based configuration system. A typical Ant build file demonstrated its declarative approach:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-xml" data-lang="xml">&lt;project name="MyFirstAntProject" default="compile" basedir="."&gt;
    &lt;property name="src.dir" location="src" /&gt;
    &lt;property name="build.dir" location="bin" /&gt;

    &lt;target name="clean"&gt;
        &lt;delete dir="${build.dir}" /&gt;
    &lt;/target&gt;

    &lt;target name="compile" depends="clean"&gt;
        &lt;javac srcdir="${src.dir}" destdir="${build.dir}" /&gt;
    &lt;/target&gt;
&lt;/project&gt;</code></pre>
</div>
</div>
<div class="paragraph">
<p>Ant succeeded in providing platform-independent build automation and flexible task execution. Its XML-based configuration allowed detailed control over build processes, and its extensible architecture supported custom tasks and complex build workflows.</p>
</div>
<div class="paragraph">
<p>However, Ant&#8217;s imperative approach became increasingly cumbersome as projects grew in complexity. The lack of dependency management, standardized project layouts, and convention-over-configuration principles made Ant builds verbose and difficult to maintain. Maven&#8217;s introduction of automatic dependency resolution and Gradle&#8217;s programmatic build scripts eventually displaced Ant in most modern Java projects.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_netscape_navigator_the_pioneer_that_lost_the_war">Netscape Navigator: The Pioneer That Lost the War</h2>
<div class="sectionbody">
<div class="paragraph">
<p>Netscape Navigator pioneered web browsing and helped create the modern internet, but ultimately fell victim to Microsoft&#8217;s aggressive competitive tactics and strategic missteps. Despite its early dominance, Netscape&#8217;s market share collapsed in the late 1990s.</p>
</div>
<div class="paragraph">
<p>Netscape Navigator introduced fundamental web technologies including JavaScript, SSL encryption, and dynamic HTML capabilities. The browser&#8217;s plugin architecture and standards-based approach laid the foundation for modern web development and demonstrated the potential for rich, interactive web applications.</p>
</div>
<div class="paragraph">
<p>However, Netscape&#8217;s downfall illustrates how market leadership can quickly evaporate in fast-moving technology sectors. Microsoft leveraged its Windows monopoly to bundle Internet Explorer with every PC, making it the default browser for millions of users. Netscape also made strategic errors, including focusing too heavily on enterprise solutions while neglecting the consumer market, allowing Microsoft to catch up and eventually surpass Netscape&#8217;s technical capabilities.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_adobe_flash_actionscript_a_multimedia_giants_swift_decline">Adobe Flash + ActionScript: A Multimedia Giant&#8217;s Swift Decline</h2>
<div class="sectionbody">
<div class="paragraph">
<p>For over a decade, Adobe Flash was the dominant platform for rich multimedia content on the web. Powered by ActionScript, a scripting language similar to JavaScript, Flash enabled highly interactive websites, games, and animations. A classic snippet of ActionScript might look like:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-actionscript" data-lang="actionscript">var myText:TextField = new TextField();
myText.text = "Hello, World!";
myText.x = 100;
myText.y = 100;
addChild(myText);</code></pre>
</div>
</div>
<div class="paragraph">
<p>This interactivity revolutionized early web experiences, making Flash a staple in web development and advertising. ActionScript 3.0 introduced object-oriented features, bringing more structure and power to web applications.</p>
</div>
<div class="paragraph">
<p>Despite its popularity, Flash faced mounting criticism for its performance, security vulnerabilities, and closed ecosystem. The death knell came when Apple declined to support Flash on iOS, signaling the industry&#8217;s shift toward open standards like HTML5, CSS3, and JavaScript. Adobe officially ended Flash support in 2020.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_visual_basic_accessibility_meets_obsolescence">Visual Basic: Accessibility Meets Obsolescence</h2>
<div class="sectionbody">
<div class="paragraph">
<p>Microsoft’s Visual Basic (VB) democratized Windows software development in the 1990s. Its simple syntax and drag-and-drop interface allowed non-programmers and beginners to create full-fledged Windows applications rapidly:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-vb" data-lang="vb">Module Module1
   Sub Main()
     Console.WriteLine("Hello World!")
   End Sub
End Module</code></pre>
</div>
</div>
<div class="paragraph">
<p>VB&#8217;s tight integration with the Windows API and rapid application development tools made it a hit for business applications. However, as .NET and more modern languages like C# emerged, Visual Basic was gradually phased out. VB.NET, its successor, attempted modernization but lacked traction among new developers.</p>
</div>
<div class="paragraph">
<p>The rise of more versatile, cross-platform, and open-source development frameworks ultimately made Visual Basic an outdated choice for contemporary software needs.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_fortran_the_long_reigning_king_of_scientific_computing">Fortran: The Long-Reigning King of Scientific Computing</h2>
<div class="sectionbody">
<div class="paragraph">
<p>Developed in the 1950s, Fortran (FORmula TRANslation) was one of the first high-level programming languages. Its strength in numerical computation made it the go-to choice for scientists and engineers for decades. A basic Fortran program might look like:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-fortran" data-lang="fortran">PROGRAM Hello
   PRINT *, 'Hello, world!'
END PROGRAM Hello</code></pre>
</div>
</div>
<div class="paragraph">
<p>Fortran introduced critical concepts like structured programming and efficient array handling, which made it ideal for high-performance computing tasks such as climate modeling and computational fluid dynamics.</p>
</div>
<div class="paragraph">
<p>Though still used in legacy scientific codebases, Fortran&#8217;s relevance has dwindled. Modern languages like Python, with libraries like NumPy and SciPy, offer more flexible and accessible alternatives, leading to Fortran’s slow fade from the mainstream.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_smalltalk_object_oriented_pioneer_with_limited_reach">Smalltalk: Object-Oriented Pioneer with Limited Reach</h2>
<div class="sectionbody">
<div class="paragraph">
<p>Smalltalk was a trailblazer in object-oriented programming. It introduced core concepts such as message passing, live coding environments, and a uniform object model that inspired languages like Java, Python, and Ruby. A Smalltalk code example:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-smalltalk" data-lang="smalltalk">Transcript show: 'Hello, world!'; cr.</code></pre>
</div>
</div>
<div class="paragraph">
<p>The entire environment was built from objects, offering unprecedented dynamism and introspection. Smalltalk&#8217;s interactive IDE and immediate feedback loop remain unmatched in some respects.</p>
</div>
<div class="paragraph">
<p>Yet, Smalltalk struggled with adoption due to performance issues, steep learning curves, and limited tooling outside its own ecosystem. While it remains influential in academic and niche circles, it was overshadowed by more pragmatic object-oriented languages that better integrated with mainstream operating systems and development workflows.</p>
</div>
</div>
</div>
<h1 id="_hardware_nightmares_when_innovation_meets_market_reality" class="sect0">Hardware Nightmares: When Innovation Meets Market Reality</h1>
<div class="paragraph">
<p>Windows Phone, Google Glass, Microsoft Zune, and Netscape Navigator represent fascinating case studies of hardware and platforms that, despite their technical innovations, faced significant challenges in achieving lasting market success. Each offers valuable lessons about the complex relationship between technological capability and commercial viability.</p>
</div>
<div class="sect1">
<h2 id="_windows_phone_microsofts_7_6_billion_lesson">Windows Phone: Microsoft&#8217;s $7.6 Billion Lesson</h2>
<div class="sectionbody">
<div class="paragraph">
<p>Microsoft&#8217;s Windows Phone stands as one of tech&#8217;s most expensive failures, with the company writing off $7.6 billion related to the Nokia acquisition. Despite having superior hardware and a polished user interface, Windows Phone never gained meaningful market share.</p>
</div>
<div class="paragraph">
<p>The platform featured a unique tile-based interface that demonstrated Microsoft&#8217;s innovative approach to mobile design. This Live Tile system showcased Windows Phone&#8217;s dynamic interface capabilities and integration with the broader Windows ecosystem. The platform&#8217;s Metro design language influenced modern UI design principles and demonstrated Microsoft&#8217;s vision for unified experiences across devices.</p>
</div>
<div class="paragraph">
<p>However, Windows Phone&#8217;s failure stemmed from entering the market too late and creating a vicious ecosystem cycle. Microsoft launched Windows Phone 7 in 2010, three years after the iPhone had already transformed the industry. By then, iOS and Android had established dominant positions with hundreds of thousands of apps, while Windows Phone launched with only 2,000. The platform suffered from a destructive cycle where low user adoption meant developers ignored the platform, which in turn meant fewer apps, leading to even lower adoption.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_google_glass_the_wearable_that_wasnt_ready_for_society">Google Glass: The Wearable That Wasn&#8217;t Ready for Society</h2>
<div class="sectionbody">
<div class="paragraph">
<p>Google Glass generated enormous hype as the future of wearable computing but crashed spectacularly due to privacy concerns and social acceptance issues. Despite Google&#8217;s technological prowess, the product was discontinued just two years after its 2013 launch.</p>
</div>
<div class="paragraph">
<p>The Glass platform introduced revolutionary concepts in augmented reality and hands-free computing. Its voice recognition capabilities and heads-up display technology influenced modern AR development and demonstrated the potential for seamless human-computer interaction through voice commands and gesture controls.</p>
</div>
<div class="paragraph">
<p>However, Google Glass faced a perfect storm of problems that made it unsuitable for mainstream adoption. The $1,500 price tag made it inaccessible to most consumers, while the device&#8217;s bulky design and visible camera created immediate privacy concerns. People worried about being recorded without consent, leading to bans in restaurants, bars, and other public spaces. Most critically, Google failed to clearly define the target market and value proposition for everyday users.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_microsoft_zune_the_ipod_killer_that_never_was">Microsoft Zune: The iPod Killer That Never Was</h2>
<div class="sectionbody">
<div class="paragraph">
<p>Microsoft&#8217;s Zune music player launched in 2006 as a direct competitor to Apple&#8217;s iPod but failed to make a significant dent in Apple&#8217;s market dominance. Despite some innovative features, the Zune became synonymous with Microsoft&#8217;s inability to compete in consumer electronics.</p>
</div>
<div class="paragraph">
<p>Zune introduced innovative wireless sharing capabilities and social music discovery features that predated modern streaming services. Its larger screen and improved navigation demonstrated Microsoft&#8217;s understanding of user interface design, while the Zune software provided a more integrated media management experience than many competitors.</p>
</div>
<div class="paragraph">
<p>However, the Zune suffered from classic late-mover disadvantages. By 2006, the iPod had already established itself as the dominant music player, with a mature ecosystem including iTunes and strong brand loyalty. Microsoft&#8217;s device offered improvements like wireless sharing and a larger screen, but these incremental benefits weren&#8217;t enough to overcome Apple&#8217;s head start. Microsoft also struggled with marketing and brand positioning, lacking the sleek design aesthetic that made Apple products desirable.</p>
</div>
</div>
</div>
<h1 id="_conclusion_lessons_in_technology_adoption" class="sect0">Conclusion: Lessons in Technology Adoption</h1>
<div class="paragraph">
<p>The histories of these varied technologies illustrate a critical lesson: technical merit alone is insufficient to guarantee market success. Whether it&#8217;s a programming language like ALGOL that lacked commercial focus, a framework like Japronto whose benchmark performance was impractical for real-world use, or hardware like the Zune and Windows Phone that couldn&#8217;t overcome established ecosystems, the pattern is consistent.</p>
</div>
<div class="paragraph">
<p>Sustainable adoption requires a delicate balance of innovation with practical usability, strong industry support, and the ability to evolve alongside changing user needs and market dynamics. The failure to address real-world problems, build a supportive ecosystem, or adapt to new industry standards ultimately led to the decline of these once-promising technologies.</p>
</div>
<]]></content:encoded>
					
		
		
			</item>
         
	<item>
		<title>A brief introduction to HyperLogLog++</title>
		<link>https://blog.lunatech.com//posts/2025-06-13-hyperloglog</link>
		
		<dc:creator><![CDATA[Alberto]]></dc:creator>
        <pubDate>2025-06-13T00:00:00.000Z</pubDate>
         
             {
            <category><![CDATA[hyperloglog]]></category>
                }
             {
            <category><![CDATA[algorithm]]></category>
                }
             {
            <category><![CDATA[randomized-algorithm]]></category>
                }
             {
            <category><![CDATA[beyond-the-code]]></category>
                }
             {
            <category><![CDATA[bash-to-the-feature]]></category>
                }
             {
            <category><![CDATA[en]]></category>
                }
             
        
		<guid isPermaLink="false">https://blog.lunatech.com//posts/2025-06-13-hyperloglog</guid>

					<description>
                        <![CDATA[ This document demonstrates a fascinating technique that tackles a complex computational problem using an elegant probabilistic strategy.]]></description>
                    <content:encoded><![CDATA[
                    <div id="toc" class="toc">
<div id="toctitle">Table of Contents</div>
<ul class="sectlevel1">
<li><a href="#introduction">The Problem</a></li>
<li><a href="#_the_algorithm">The Algorithm</a></li>
<li><a href="#_example">Example</a></li>
<li><a href="#_implementation">Implementation</a>
<ul class="sectlevel2">
<li><a href="#_data_structure">Data Structure</a></li>
<li><a href="#_add_operation">Add Operation</a></li>
<li><a href="#_count_operation">Count Operation</a></li>
<li><a href="#_merge_operation">Merge Operation</a></li>
</ul>
</li>
<li><a href="#_relative_percentage_error">Relative Percentage Error</a></li>
<li><a href="#_conclusion">Conclusion</a></li>
</ul>
</div>
<div id="preamble">
<div class="sectionbody">
<div class="paragraph">
<p>This document demonstrates a fascinating technique that tackles a complex computational problem using an elegant probabilistic strategy.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="introduction">The Problem</h2>
<div class="sectionbody">
<div class="paragraph">
<p>The <strong>count-distinct problem</strong> (also known as the <em>cardinality estimation problem</em>) involves finding the number of distinct elements in a data stream containing repeated elements.</p>
</div>
<div class="paragraph">
<p>Traditionally, solving this problem requires Θ(D) space complexity, where D represents the number of unique elements. This is because we need to store each unique element to determine whether a new element has been previously encountered.</p>
</div>
<div class="paragraph">
<p>Unfortunately, this approach doesn&#8217;t scale for massive cardinalities found in real-world applications such as:</p>
</div>
<div class="ulist">
<ul>
<li>
<p><strong>Unique Query Counting</strong>: Tracking the number of unique searches in a search engine</p>
</li>
<li>
<p><strong>Network Monitoring</strong>: Counting unique source IP addresses</p>
</li>
<li>
<p><strong>Unique Visitor Tracking</strong>: Monitoring distinct users across web platforms</p>
</li>
</ul>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<div class="title">Note</div>
</td>
<td class="content">
In the original paper and related literature, "cardinality" refers to the number of distinct elements.
</td>
</tr>
</table>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_the_algorithm">The Algorithm</h2>
<div class="sectionbody">
<div class="paragraph">
<p>When you only need an estimation, or when the number of unique elements makes it impractical to store them all in memory, <strong>HyperLogLog++</strong> provides an excellent solution.</p>
</div>
<div class="paragraph">
<p>This technique estimates the number of unique elements with a relative percentage error between -4% and 6%, using only 16 KB of memory (though this depends on the number of registers configured).</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_example">Example</h2>
<div class="sectionbody">
<div class="paragraph">
<p>Let me illustrate the core concept with a simple analogy.</p>
</div>
<div class="paragraph">
<p>Imagine someone spends an entire day rolling a die and tells you the maximum number of consecutive 1s they rolled was 3. While you can&#8217;t determine the exact number of rolls, you can estimate it by calculating the probability of this event occurring.</p>
</div>
<div class="paragraph">
<p>The probability of rolling three consecutive 1s is:</p>
</div>
<div class="literalblock">
<div class="content">
<pre>1/6 * 1/6 * 1/6 = 1/(6^3)</pre>
</div>
</div>
<div class="paragraph">
<p>Therefore, the expected number of trials needed to observe this event is:</p>
</div>
<div class="literalblock">
<div class="content">
<pre>1 / (1/6^3) = 6^3 = 216</pre>
</div>
</div>
<div class="paragraph">
<p>Translating this concept into an algorithm:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>The <strong>Dice game</strong> becomes a Hash function that hashes the element in input and yields bits. These bits represent the outcome of the game run, like if the dice had only two faces, 1 and 0.</p>
</li>
<li>
<p>The event taken into account was that the longest sequence of 1&#8217;s (that the die returns 1) at the start of the game, but in this case, since hashing returns a binary output, the algorithm will calculate the event of longest run of leading bits set to 0. Technically, it&#8217;s also possible to count leading ones, but counting leading zeros is a common convention.</p>
</li>
<li>
<p><strong>Probability of rolling a 1 (1/6)</strong> → Probability of a bit being 0 (1/2)</p>
</li>
<li>
<p><strong>Number of plays</strong> → Cardinality</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>This represents the fundamental idea behind the Flajolet–Martin algorithm, which HyperLogLog improves upon through three key enhancements.
*Correction Factor* is applied to mitigate the overestimation bias inherent in the standard HLL algorithm.
*Grouped Averaging* specifically the harmonic mean across multiple registers (or buckets), to significantly improve the accuracy of its cardinality estimates.
HLL for small cardinalities suffers from the Overestimation Bias, for that reason <strong>Linear Counting</strong> is used, which is another probabilistic counting algorithm simple and highly accurate for that scale.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_implementation">Implementation</h2>
<div class="sectionbody">
<div class="sect2">
<h3 id="_data_structure">Data Structure</h3>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">class HyperLogLog {
    //Number of registers. Must be a power of 2. `buckets = 2^p`
    private final int buckets = 16384;

    // Correction factor
    private final double alpha = 0.7213 / (1 + 1.079 / buckets); //0.72125250052

    //Initialize the array of 16 383 (2^14-1) elements
    private final byte[] registers = new byte[buckets];</code></pre>
</div>
</div>
<div class="paragraph">
<p>The hash function outputs 64 bits, the first 14 are used to address the registers while the last 50 are used for calculating the ranking.
That&#8217;s why the size of the register array is <code>16384</code> and the type is <code>byte</code> sufficient to count up to 50 leading zeros.</p>
</div>
</div>
<div class="sect2">
<h3 id="_add_operation">Add Operation</h3>
<div class="paragraph">
<p>The <code>add</code> operation is how you feed individual elements into the HyperLogLog structure. The goal is to update the internal state of the HLL to reflect the presence of this new element.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">    public void add(String element) {
        // Calculate hash
        long hash = hashElement(element);
        // Take the first 14 bits to address the register
        short registerIndex = getIndex(hash);
        // Take the last 50 bits
        long value = getValue(hash);
        // Calculate the rank value for the target register
        byte rank = (byte) (leadingZeros(value) + 1);
        // Keep the biggest rank between rank and registers[registerIndex]
        if (rank &gt; registers[registerIndex]) {
            registers[registerIndex] = rank;
        }
    }</code></pre>
</div>
</div>
<div class="olist arabic">
<ol class="arabic">
<li>
<p><strong>Calculate</strong> a 64-bit hash of the input</p>
</li>
<li>
<p><strong>Extract</strong> the first 14 bits of the hash to index the register</p>
</li>
<li>
<p><strong>Use</strong> the remaining 50 bits to calculate the number of leading zeros</p>
</li>
<li>
<p><strong>Compare</strong> with the existing register value and store the biggest rank</p>
</li>
</ol>
</div>
</div>
<div class="sect2">
<h3 id="_count_operation">Count Operation</h3>
<div class="paragraph">
<p>The <code>count</code> operation provides an approximation of the number of distinct elements that have been added to the HyperLogLog.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">    public long count() {
        double sum = 0;
        int zeroRegisters = 0;
        // Calculate the harmonic mean of the register values
        for (byte register: registers) {
            sum += Math.pow(2, -register);
            if (register == 0) {
                zeroRegisters++;
            }
        }
        // Raw estimate
        double estimate = alpha * buckets * buckets / sum;
        // Apply corrections for small cardinalities
        if (estimate &lt;= 2.5 * m &amp;&amp; zeroRegisters &gt; 0) {
            // Linear counting
            estimate = buckets * Math.log((double) buckets / zeroRegisters);
        }
        return Math.round(estimate);
    }</code></pre>
</div>
</div>
<div class="olist arabic">
<ol class="arabic">
<li>
<p><strong>Calculate</strong> the harmonic mean of all register values</p>
</li>
<li>
<p><strong>Apply</strong> a correction factor</p>
</li>
<li>
<p><strong>Count</strong> the number of empty registers</p>
</li>
<li>
<p><strong>Fall back</strong> to linear counting for small cardinalities</p>
</li>
</ol>
</div>
</div>
<div class="sect2">
<h3 id="_merge_operation">Merge Operation</h3>
<div class="paragraph">
<p>The <code>merge</code> operation allows you to combine two or more HyperLogLog structures into a new HLL structure (or update one with another). This is a powerful feature for distributed systems where distinct counts might be computed on subsets of data in parallel and then combined.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">    public void merge(HyperLogLog that) {
        for (int i = 0; i &lt; buckets; i++) {
            if (this.registers[i] &lt; that.registers[i])
                this.registers[i] = that.registers[i];
        }
    }</code></pre>
</div>
</div>
<div class="olist arabic">
<ol class="arabic">
<li>
<p><strong>Compare</strong> each register pair at the same index</p>
</li>
<li>
<p><strong>Retain</strong> the register with the larger value</p>
</li>
</ol>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_relative_percentage_error">Relative Percentage Error</h2>
<div class="sectionbody">
<div class="imageblock">
<div class="content">
<img src="../media/2025-06-13-hyperloglog/error_plot.svg" alt="Error Plot">
</div>
</div>
<div class="paragraph">
<p>In this graph x-axis represents the expected cardinality, and it goes from 0 to 100k elements.
While the y-axis represents the relative error in percentage.
We can observe that in the first part that linear counting is used for cardinalities up to approximately 40,000, after which HyperLogLog++ takes over, the error is quite high, but it starts to converge around 0 the more elements come in.
The next graph shows what would happen without linear counting, the Overestimation Bias.</p>
</div>
<div class="imageblock">
<div class="content">
<img src="../media/2025-06-13-hyperloglog/no_linear_counting.svg" alt="No Linear Counting">
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_conclusion">Conclusion</h2>
<div class="sectionbody">
<div class="paragraph">
<p>HyperLogLog++ is a good solution for counting unique elements in those use case where storing them in memory is not practical.
It provides O(1) complexity both in terms of time and space, and the relative error is in the range of -4% to 6%.</p>
</div>
<div class="imageblock">
<div class="content">
<img src="../media/2025-06-13-hyperloglog/flajolet_philippe_small.jpg" alt="Philippe Flajolet">
</div>
</div>
<div class="paragraph">
<p><em>Philippe Flajolet - First author of "HyperLogLog: the analysis of a near-optimal
cardinality estimation algorithm"</em></p>
</div>
</div>
</div>
<]]></content:encoded>
					
		
		
			</item>
         
	<item>
		<title>A Quest to Tame Large Language Models</title>
		<link>https://blog.lunatech.com//posts/2025-05-26-demystify-LLMs</link>
		
		<dc:creator><![CDATA[Luke Woodcock]]></dc:creator>
        <pubDate>2025-05-26T00:00:00.000Z</pubDate>
         
             {
            <category><![CDATA[LLM]]></category>
                }
             {
            <category><![CDATA[natural language processing]]></category>
                }
             {
            <category><![CDATA[transformers]]></category>
                }
             {
            <category><![CDATA[machine learning]]></category>
                }
             {
            <category><![CDATA[AI]]></category>
                }
             {
            <category><![CDATA[language models]]></category>
                }
             {
            <category><![CDATA[probabilistic text generation]]></category>
                }
             {
            <category><![CDATA[statistical language models]]></category>
                }
             {
            <category><![CDATA[n-gram]]></category>
                }
             {
            <category><![CDATA[bigram]]></category>
                }
             {
            <category><![CDATA[attention mechanisms]]></category>
                }
             {
            <category><![CDATA[vector embeddings]]></category>
                }
             {
            <category><![CDATA[tokenization]]></category>
                }
             {
            <category><![CDATA[context windows]]></category>
                }
             {
            <category><![CDATA[self-attention]]></category>
                }
             {
            <category><![CDATA[neural networks]]></category>
                }
             {
            <category><![CDATA[NLP fundamentals]]></category>
                }
             {
            <category><![CDATA[AI architecture]]></category>
                }
             {
            <category><![CDATA[language understanding]]></category>
                }
             {
            <category><![CDATA[transformer architecture]]></category>
                }
             {
            <category><![CDATA[en]]></category>
                }
             
        
		<guid isPermaLink="false">https://blog.lunatech.com//posts/2025-05-26-demystify-LLMs</guid>

					<description>
                        <![CDATA[ Large Language Models represent one of the most significant advances in artificial intelligence, fundamentally transforming how we interact with natural language processing systems. Understanding their architecture and mechanisms is essential for anyone working with modern AI systems.]]></description>
                    <content:encoded><![CDATA[
                    <div id="toc" class="toc">
<div id="toctitle">Table of Contents</div>
<ul class="sectlevel1">
<li><a href="#introduction">Introduction</a></li>
<li><a href="#_1_the_foundation_probabilistic_text_generation">1. The Foundation: Probabilistic Text Generation</a>
<ul class="sectlevel2">
<li><a href="#_statistical_language_models">Statistical Language Models</a></li>
<li><a href="#_bi_gram_models">Bi-gram Models</a></li>
<li><a href="#_n_gram_models">N-gram Models</a></li>
</ul>
</li>
<li><a href="#_2_the_transformer_revolution_attention_is_all_you_need">2. The Transformer Revolution: "Attention is All You Need"</a>
<ul class="sectlevel2">
<li><a href="#_vector_representations">Vector Representations</a></li>
<li><a href="#_attention_mechanisms">Attention Mechanisms</a></li>
<li><a href="#_attention_architecture">Attention Architecture</a></li>
</ul>
</li>
<li><a href="#_technical_glossary">Technical Glossary</a>
<ul class="sectlevel2">
<li><a href="#_attention_mechanism">attention mechanism</a></li>
<li><a href="#_bigram_model">bigram model</a></li>
<li><a href="#_byte_pair_encoding">byte-pair encoding</a></li>
<li><a href="#_context">context</a></li>
<li><a href="#_corpus">corpus</a></li>
<li><a href="#_data_sparsity">data sparsity</a></li>
<li><a href="#_embedding">embedding</a></li>
<li><a href="#_epoch">epoch</a></li>
<li><a href="#_hyperparameter">hyperparameter</a></li>
<li><a href="#_long_range_dependencies">long range dependencies</a></li>
<li><a href="#_loss">loss</a></li>
<li><a href="#_n_gram_model">n-gram model</a></li>
<li><a href="#_over_fitting">over-fitting</a></li>
<li><a href="#_parameter">parameter</a></li>
<li><a href="#_parameter_space">parameter space</a></li>
<li><a href="#_preprocessing">preprocessing</a></li>
<li><a href="#_temperature">temperature</a></li>
<li><a href="#_token">token</a></li>
<li><a href="#_tokenization">tokenization</a></li>
<li><a href="#_training">training</a></li>
<li><a href="#_transformer">transformer</a></li>
<li><a href="#_vector">vector</a></li>
</ul>
</li>
</ul>
</div>
<div class="sect1">
<h2 id="introduction">Introduction</h2>
<div class="sectionbody">
<div class="paragraph">
<p>Large Language Models represent one of the most significant advances in artificial intelligence, fundamentally transforming how we interact with natural language processing systems. Understanding their architecture and mechanisms is essential for anyone working with modern AI systems.</p>
</div>
<div class="paragraph">
<p>This guide examines the core concepts underlying LLMs, from foundational statistical models to sophisticated attention mechanisms, providing practical insights for implementation and deployment. We&#8217;ll explore how these systems generate coherent text, the role of context in language understanding, and the architectural innovations that enable modern capabilities.</p>
</div>
<div class="paragraph">
<p>If new to the language of LLMs, this guide aims to demystify some of the "magic" surrounding them. If already versed in the language of LLMs, this guide hopes to be a refresher.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_1_the_foundation_probabilistic_text_generation">1. The Foundation: Probabilistic Text Generation</h2>
<div class="sectionbody">
<div class="imageblock">
<div class="content">
<img src="../media/2025-05-26-demystify-LLMs/cotton-probability-machine-simple-compose.jpg" alt="Embroidered probability machine" width="900">
</div>
</div>
<div class="paragraph">
<p>Large Language Models operate as sophisticated probability machines. At their core, they analyze patterns in text data to predict the most likely next token given a specific context. While they incorporate stochastic elements through temperature controls, pedantically, their underlying mechanisms are fundamentally deterministic—the same prompt with identical parameters will consistently produce the same output. In pratice, however, they are far from determinisitic—the stochastic elements and numerous other caveats render that statement for "illustration purposes only".</p>
</div>
<div class="sect2">
<h3 id="_statistical_language_models">Statistical Language Models</h3>
<div class="paragraph">
<p>Statistical language models form the conceptual foundation for understanding modern LLMs. These models process a <a href="#_corpus">corpus</a> of text and use statistical patterns to predict subsequent words or <a href="#_tokenization">tokens</a>. While contemporary LLMs have evolved far beyond these simple approaches, understanding statistical models illuminates the core challenges that advanced architectures address.</p>
</div>
</div>
<div class="sect2">
<h3 id="_bi_gram_models">Bi-gram Models</h3>
<div class="paragraph">
<p>A <a href="#_bigram_model">bigram model</a> represents the simplest form of statistical language modeling. It analyzes pairs of consecutive words to build frequency tables that inform predictions.</p>
</div>
<div class="paragraph">
<p>Consider this example corpus:
<em>"The cat sat on the mat. The mat was soft and warm."</em></p>
</div>
<div class="imageblock">
<div class="content">
<img src="../media/2025-05-26-demystify-LLMs/cat_on_warm_mat_simple_compose.jpg" alt="Embroidered cat on an embroidered mat" width="900">
</div>
</div>
<div class="paragraph">
<p>The resulting bi-gram frequency table would contain:</p>
</div>
<table class="tableblock frame-all grid-all stretch">
<colgroup>
<col style="width: 50%;">
<col style="width: 50%;">
</colgroup>
<thead>
<tr>
<th class="tableblock halign-left valign-top">Bigram</th>
<th class="tableblock halign-left valign-top">Count</th>
</tr>
</thead>
<tbody>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">The cat</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">1</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">cat sat</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">1</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">sat on</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">1</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">on the</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">1</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">the mat</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">2</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">mat The</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">1</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">was soft</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">1</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">soft and</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">1</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">and warm</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">1</p></td>
</tr>
</tbody>
</table>
<div class="paragraph">
<p>When processing the input "The," the model examines all bi-grams beginning with "The":</p>
</div>
<div class="ulist">
<ul>
<li>
<p>"The cat" (1 occurrence)</p>
</li>
<li>
<p>"The mat" (2 occurrences)</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>The model predicts "mat" as the most probable next word based on frequency.</p>
</div>
<div class="paragraph">
<p>While effective for demonstration, <a href="#_bigram_model">bigram models</a> suffer from severe contextual limitations, because the consider only one preceding word for their predictions.</p>
</div>
</div>
<div class="sect2">
<h3 id="_n_gram_models">N-gram Models</h3>
<div class="paragraph">
<p>The <a href="#_n_gram_model">n-gram model</a> extends the bi-gram concept by incorporating longer <a href="#_context">contextual windows</a>. A trigram model, for example, considers two preceding words, while an n-gram model employs n-1 words of context.</p>
</div>
<div class="paragraph">
<p>Let&#8217;s look at the sentence: <em>"Thank you very much for your cooperation. I very much appreciated it. We very much made progress."</em></p>
</div>
<div class="paragraph">
<p>A trigram model encountering "you very" would leverage both "you" and "very" to predict "much," using conditional probability <strong><em>P("much" | "you", "very")</em>.</strong></p>
</div>
<div class="paragraph">
<p>The relationship between context length and model performance involves critical trade-offs:</p>
</div>
<div class="paragraph">
<p><strong>Longer Context (Higher n):</strong></p>
</div>
<div class="ulist">
<ul>
<li>
<p>Captures richer contextual dependencies</p>
</li>
<li>
<p>Enables more coherent text generation</p>
</li>
<li>
<p>Increases model complexity and <a href="#_parameter_space">parameter space</a></p>
</li>
<li>
<p>Higher risk of <a href="#_data_sparsity">data sparsity</a></p>
</li>
</ul>
</div>
<div class="paragraph">
<p><strong>Shorter Context (Lower n):</strong></p>
</div>
<div class="ulist">
<ul>
<li>
<p>Simpler models with fewer parameters</p>
</li>
<li>
<p>More robust probability estimates</p>
</li>
<li>
<p>Limited contextual understanding</p>
</li>
<li>
<p>Reduced coherence in generated text</p>
</li>
</ul>
</div>
<div class="paragraph">
<p><a href="#_data_sparsity">Data sparsity</a> becomes increasingly problematic as n increases—many <a href="#_n_gram_model">n-grams</a> may not appear frequently enough in training data to provide reliable probability estimates.</p>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_2_the_transformer_revolution_attention_is_all_you_need">2. The Transformer Revolution: "Attention is All You Need"</h2>
<div class="sectionbody">
<div class="paragraph">
<p>The transformer architecture, introduced by Google researchers, revolutionized natural language processing by solving the contextual limitations of <a href="#_n_gram_model">n-gram models</a> through sophisticated <a href="#_attention_mechanism">attention mechanisms</a>.</p>
</div>
<div class="sect2">
<h3 id="_vector_representations">Vector Representations</h3>
<div class="paragraph">
<p><a href="#_transformer">Transformers</a> convert words and <a href="#_token">tokens</a> into high-dimensional <a href="#_vector">vectors</a> (<a href="#_embedding">embeddings</a>) that capture semantic and syntactic relationships. Unlike sequential models that process text word-by-word, transformers can analyze relationships between all words in a passage simultaneously.</p>
</div>
<div class="paragraph">
<p><strong>Vector Dimensionality:</strong></p>
</div>
<div class="ulist">
<ul>
<li>
<p>2D vectors contain 2 numbers (analogous to map coordinates)</p>
</li>
<li>
<p>3D vectors contain 3 numbers (spatial coordinates)</p>
</li>
<li>
<p>LLM vectors are high-dimensional with hundreds or thousands of dimensions</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>Each dimension in an <a href="#_vector">vector</a> space captures different aspects of meaning, enabling the model to represent complex relationships between words and concepts. Vectors occupying similar positions in this space represent semantically related concepts.</p>
</div>
</div>
<div class="sect2">
<h3 id="_attention_mechanisms">Attention Mechanisms</h3>
<div class="paragraph">
<p>An <a href="#_attention_mechanism">attention mechanism</a> functions as a dynamic spotlight, highlighting relevant information during text processing. For each <a href="#_token">token</a>, the model calculates attention weights determining how much focus to allocate to every other token in the context.</p>
</div>
<div class="paragraph">
<p><strong>Key Advantages:</strong></p>
</div>
<div class="ulist">
<ul>
<li>
<p><strong>Long-range Dependencies:</strong> Links related information across distant text portions</p>
</li>
<li>
<p><strong>Context-Aware Processing:</strong> Resolves ambiguous words based on surrounding context</p>
</li>
<li>
<p><strong>Parallel Processing:</strong> Analyzes all relationships simultaneously rather than sequentially</p>
</li>
</ul>
</div>
</div>
<div class="sect2">
<h3 id="_attention_architecture">Attention Architecture</h3>
<div class="paragraph">
<p><a href="#_attention_mechanism">Attention mechanisms</a> operate through three primary components for each <a href="#_token">token</a>:</p>
</div>
<div class="olist arabic">
<ol class="arabic">
<li>
<p><strong>Query Vector:</strong> Represents what the current token is "looking for"</p>
</li>
<li>
<p><strong>Key Vector:</strong> Represents what each token "offers" as context</p>
</li>
<li>
<p><strong>Value Vector:</strong> Contains the actual information to be combined</p>
</li>
</ol>
</div>
<div class="paragraph">
<p><strong>Processing Steps:</strong></p>
</div>
<div class="olist arabic">
<ol class="arabic">
<li>
<p>Generate query, key, and value vectors for each token</p>
</li>
<li>
<p>Compare the current token&#8217;s query with all tokens' keys</p>
</li>
<li>
<p>Calculate attention scores indicating relevance strength</p>
</li>
<li>
<p>Use scores to weight value vectors</p>
</li>
<li>
<p>Combine weighted values to produce final token representation</p>
</li>
</ol>
</div>
<div class="paragraph">
<p><strong>Attention Weight Properties:</strong></p>
</div>
<div class="ulist">
<ul>
<li>
<p>Higher weights indicate stronger relevance</p>
</li>
<li>
<p>Weights are normalized to form probability distributions (sum to 1)</p>
</li>
<li>
<p>Enable the model to focus on the most contextually relevant information</p>
</li>
</ul>
</div>
<div class="paragraph">
<p><strong>Self-Attention:</strong></p>
</div>
<div class="paragraph">
<p>Every token in a sequence attends to all others, including itself, capturing comprehensive contextual relationships across the entire sequence.</p>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_technical_glossary">Technical Glossary</h2>
<div class="sectionbody">
<div class="sect2">
<h3 id="_attention_mechanism">attention mechanism</h3>
<div class="paragraph">
<p>Mechanisms that enable models to weigh the importance of different input portions relative to each other, focusing on the most relevant information for accurate and coherent output generation.</p>
</div>
</div>
<div class="sect2">
<h3 id="_bigram_model">bigram model</h3>
<div class="paragraph">
<p>Statistical models that predict the next word based on the immediately preceding word, analyzing word pair frequencies to determine probability distributions.</p>
</div>
</div>
<div class="sect2">
<h3 id="_byte_pair_encoding">byte-pair encoding</h3>
<div class="paragraph">
<p>An algorithm for creating efficient tokenization by:</p>
</div>
<div class="olist arabic">
<ol class="arabic">
<li>
<p>Counting character frequencies in the corpus</p>
</li>
<li>
<p>Identifying the most common character pairs</p>
</li>
<li>
<p>Adding common pairs to the vocabulary</p>
</li>
<li>
<p>Iteratively building tokens from frequent patterns</p>
</li>
</ol>
</div>
</div>
<div class="sect2">
<h3 id="_context">context</h3>
<div class="paragraph">
<p>The surrounding words or sequences that inform next-word prediction. Context length varies by model type—<a href="#_bigram_model">bigram models</a> use 1 word, trigram models use 2 words, and <a href="#_n_gram_model">ngram models</a> use n-1 words of context.</p>
</div>
</div>
<div class="sect2">
<h3 id="_corpus">corpus</h3>
<div class="paragraph">
<p>The comprehensive dataset of texts used for model training, typically including diverse sources such as books, articles, websites, and other written materials. Corpus quality and diversity directly impact model performance.</p>
</div>
</div>
<div class="sect2">
<h3 id="_data_sparsity">data sparsity</h3>
<div class="paragraph">
<p>Insufficient coverage of possible inputs or features in training data, where certain patterns may not appear frequently enough to provide reliable probability estimates.</p>
</div>
</div>
<div class="sect2">
<h3 id="_embedding">embedding</h3>
<div class="paragraph">
<p>Embeddings transform symbolic language into mathematical forms (the vector) that neural networks can process, with similar concepts positioned closer together in the vector space.</p>
</div>
<div class="paragraph">
<p>The terms "embedding" and "vector" are often used interchangeably in machine learning contexts, though "embedding" specifically speaks to the process of transforming data into the vector form, whereas "an embedding" likely speaks to a vector—unless a new model is invented that doesn&#8217;t use vectors.</p>
</div>
</div>
<div class="sect2">
<h3 id="_epoch">epoch</h3>
<div class="paragraph">
<p>One complete pass through the entire training dataset, during which the model processes all examples and updates parameters based on prediction errors.</p>
</div>
</div>
<div class="sect2">
<h3 id="_hyperparameter">hyperparameter</h3>
<div class="paragraph">
<p>A configuration setting that influences model behavior but is not learned during training. Examples include learning rate, batch size, and temperature. Hyperparameters are typically set before training begins and can significantly impact model performance.</p>
</div>
</div>
<div class="sect2">
<h3 id="_long_range_dependencies">long range dependencies</h3>
<div class="paragraph">
<p>Relationships between words or phrases separated by significant distances in text, such as pronouns referring to entities in different paragraphs.</p>
</div>
</div>
<div class="sect2">
<h3 id="_loss">loss</h3>
<div class="paragraph">
<p>A metric measuring prediction accuracy by quantifying the difference between model outputs and correct answers. Training progressively reduces loss through parameter optimization.</p>
</div>
</div>
<div class="sect2">
<h3 id="_n_gram_model">n-gram model</h3>
<div class="paragraph">
<p>Describes the general version of a bigram model. It is a statistical language modeling approach that predicts words based on n-1 previous words in sequence. Common variants include bigrams (n=2), trigrams (n=3).</p>
</div>
</div>
<div class="sect2">
<h3 id="_over_fitting">over-fitting</h3>
<div class="paragraph">
<p>A condition where models perform exceptionally on training data but fail to generalize to new, unseen inputs—analogous to memorizing without understanding.</p>
</div>
</div>
<div class="sect2">
<h3 id="_parameter">parameter</h3>
<div class="paragraph">
<p>The individual weights and biases within a model that are adjusted during training to minimize prediction error. Parameters are learned from the training data and define the model&#8217;s behavior.</p>
</div>
</div>
<div class="sect2">
<h3 id="_parameter_space">parameter space</h3>
<div class="paragraph">
<p>The multidimensional mathematical domain that encompasses all the weights and biases that the model can learn, which can number in the millions or billions for modern language models.</p>
</div>
</div>
<div class="sect2">
<h3 id="_preprocessing">preprocessing</h3>
<div class="paragraph">
<p>Data preparation steps including cleaning, transformation, and structuring to optimize datasets for machine learning, such as lowercasing text or removing stop words.</p>
</div>
</div>
<div class="sect2">
<h3 id="_temperature">temperature</h3>
<div class="paragraph">
<p>A hyperparameter controlling output randomness:</p>
</div>
<div class="ulist">
<ul>
<li>
<p><strong>Lower Temperature:</strong> More deterministic, focused responses with higher probability words</p>
</li>
<li>
<p><strong>Higher Temperature:</strong> Increased randomness and creativity, selecting less probable words</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>Not to be confused with the parameter space.</p>
</div>
</div>
<div class="sect2">
<h3 id="_token">token</h3>
<div class="paragraph">
<p>The fundamental unit of text processed by language models, representing a piece of text produced through tokenization. Tokens can be words, subwords, characters, or other linguistic units depending on the tokenization method used.</p>
</div>
</div>
<div class="sect2">
<h3 id="_tokenization">tokenization</h3>
<div class="paragraph">
<p>The process of segmenting text into smaller units (tokens) such as words, subwords, or characters. Effective tokenization increases training examples and enables models to learn morphological patterns.</p>
</div>
</div>
<div class="sect2">
<h3 id="_training">training</h3>
<div class="paragraph">
<p>The process of optimizing the model&#8217;s parameter space to maximize prediction accuracy, expressed as f(x|params) where x represents input and params represents learned weights.</p>
</div>
</div>
<div class="sect2">
<h3 id="_transformer">transformer</h3>
<div class="paragraph">
<p>A neural network architecture that consists of encoders (for understanding input) and decoders (for generating output), or decoder-only (for generative tasks). Transformers process all tokens in parallel rather than sequentially and better capture long range context.</p>
</div>
</div>
<div class="sect2">
<h3 id="_vector">vector</h3>
<div class="paragraph">
<p>High-dimensional numerical representations of text or data, capturing semantic and syntactic relationships in mathematical space suitable for computational processing.</p>
</div>
</div>
</div>
</div>
<]]></content:encoded>
					
		
		
			</item>
         
	<item>
		<title>Part 4: Angular 19 Deep Dive – Smarter Forms with Signals and Control Flow</title>
		<link>https://blog.lunatech.com//posts/2025-05-20-part-4:-angular-19-deep-dive-–-smarter-forms-with-signals-and-control-flow</link>
		
		<dc:creator><![CDATA[Jake Ortega]]></dc:creator>
        <pubDate>2025-05-20T00:00:00.000Z</pubDate>
         
             {
            <category><![CDATA[angular]]></category>
                }
             {
            <category><![CDATA[nestjs]]></category>
                }
             {
            <category><![CDATA[postgresql]]></category>
                }
             {
            <category><![CDATA[typeorm]]></category>
                }
             {
            <category><![CDATA[jwt]]></category>
                }
             {
            <category><![CDATA[authentication]]></category>
                }
             {
            <category><![CDATA[frontend]]></category>
                }
             {
            <category><![CDATA[typescript]]></category>
                }
             {
            <category><![CDATA[nodejs]]></category>
                }
             {
            <category><![CDATA[en]]></category>
                }
             
        
		<guid isPermaLink="false">https://blog.lunatech.com//posts/2025-05-20-part-4:-angular-19-deep-dive-–-smarter-forms-with-signals-and-control-flow</guid>

					<description>
                        <![CDATA[ Welcome back to the Full-Stack Authentication Boilerplate (Angular +]]></description>
                    <content:encoded><![CDATA[
                    <div id="preamble">
<div class="sectionbody">
<div class="paragraph">
<p>Welcome back to the Full-Stack Authentication Boilerplate (Angular<br>
NestJS + PostgreSQL) series. So far, we’ve wired up the backend and
built a working Angular frontend. Now it’s time to modernize our forms
using the latest Angular 19 features—specifically <strong>Signals</strong>, <strong>control
flow syntax</strong>, and <strong>defer blocks</strong>.</p>
</div>
<div class="paragraph">
<p>Angular 19 isn’t a total rewrite—it’s a refinement. It tightens up
template logic, improves reactivity, and lets us write cleaner, more
performant UI code. In this part, we’ll refactor the login and register
forms to take full advantage of these improvements.</p>
</div>
<hr>
</div>
</div>
<div class="sect2">
<h3 id="_angular_19_recap_and_what_actually_matters_for_devs">Angular 19 Recap (and What Actually Matters for Devs)</h3>
<div class="paragraph">
<p>Here’s what we’ll use in this part:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>✅ <strong>Signals</strong>: Angular’s native reactive primitive, lets you track
state like <code>useState()</code> in React—but fully integrated into Angular’s
change detection.</p>
</li>
<li>
<p>✅ <strong>Control Flow Syntax</strong> (<code>@if</code>, <code>@for</code>, <code>@switch</code>): Cleaner
alternatives to structural directives like <code>*ngIf</code> and <code>*ngFor</code>.</p>
</li>
<li>
<p>✅ <strong>Defer Blocks</strong>: Lazy-load parts of the UI, just like backend routes
or feature modules.</p>
</li>
<li>
<p>✅ <strong>@let Directive</strong>: Declare local variables directly in templates.</p>
</li>
<li>
<p>✅ <strong>Smarter Change Detection</strong>: Updates only the DOM parts that
actually changed, for faster UIs.</p>
</li>
</ul>
</div>
<div class="quoteblock">
<blockquote>
<div class="paragraph">
<p><strong>For backend devs:</strong> Think of <code>signal()</code> like a reactive field or an
in-memory tracked variable; <code>@if</code>/<code>@for</code> in your templates is like
having expressive, inline logic with instant UI updates—no more verbose
boilerplate.</p>
</div>
</blockquote>
</div>
<hr>
</div>
<div class="sect2">
<h3 id="_signals_or_reactive_forms">Signals or Reactive Forms?</h3>
<div class="quoteblock">
<blockquote>
<div class="paragraph">
<p><strong>When to Use Each (for Backend Devs):</strong></p>
</div>
<div class="ulist">
<ul>
<li>
<p><strong>Signals</strong> are perfect for local/component UI state and simple forms.</p>
</li>
<li>
<p><strong>Reactive Forms</strong> (<code>FormBuilder</code>, etc.) are the gold standard for
complex, validation-heavy, or dynamic forms—especially if you need
granular error handling or will scale up forms later.</p>
</li>
<li>
<p><strong>Pro Tip:</strong> You can use both! Track form state with Reactive Forms,
then reflect with signals using Angular’s <code>toSignal()</code> utility for the
best DX.</p>
</li>
</ul>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-ts" data-lang="ts">// Example: Bridge form values to signals
formValue = toSignal(form.valueChanges, { initialValue: form.value });</code></pre>
</div>
</div>
</blockquote>
</div>
<hr>
</div>
<div class="sect2">
<h3 id="_migration_ngmodules_standalone_components">Migration: NgModules → Standalone Components</h3>
<div class="quoteblock">
<blockquote>
<div class="paragraph">
<p><strong>Old way:</strong></p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-ts" data-lang="ts">@NgModule({
  declarations: [LoginComponent],
  imports: [ReactiveFormsModule],
})
export class AuthModule {}</code></pre>
</div>
</div>
<div class="paragraph">
<p><strong>New way (Angular 15+):</strong></p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-ts" data-lang="ts">@Component({
  standalone: true,
  selector: 'app-login',
  templateUrl: './login.component.html',
  imports: [ReactiveFormsModule],
})
export class LoginComponent {}</code></pre>
</div>
</div>
<div class="ulist">
<ul>
<li>
<p>No more <code>@NgModule</code> needed.</p>
</li>
<li>
<p>Use <code>standalone: true</code> and import dependencies directly in the
component.</p>
</li>
<li>
<p>Both patterns can coexist during migration.</p>
</li>
</ul>
</div>
</blockquote>
</div>
<hr>
</div>
<div class="sect2">
<h3 id="_refactoring_the_login_form">Refactoring the Login Form</h3>
<div class="paragraph">
<p>Here’s how to use Reactive Forms as the foundation, enhanced with
signals and modern control flow blocks.</p>
</div>
<div class="sect3">
<h4 id="_login_component_ts"><code>login.component.ts</code></h4>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-ts" data-lang="ts">import {
  Component,
  computed,
  signal,
  inject,
  ChangeDetectionStrategy,
} from '@angular/core';
import { Router } from '@angular/router';
import { FormBuilder, Validators, ReactiveFormsModule } from '@angular/forms';
import { AuthService } from '../../services/auth.service';
import { toSignal } from '@angular/core/rxjs-interop';
import { take } from 'rxjs/operators';

@Component({
  selector: 'app-login',
  templateUrl: './login.component.html',
  styleUrls: ['./login.component.scss'],
  standalone: true,
  imports: [ReactiveFormsModule],
  changeDetection: ChangeDetectionStrategy.OnPush,
})
export class LoginComponent {
  private readonly fb = inject(FormBuilder);
  readonly form = this.fb.group({
    email: ['', [Validators.required, Validators.email]],
    password: ['', [Validators.required, Validators.minLength(6)]],
  });

  readonly isLoading = signal(false);
  readonly errorMessage = signal&lt;string | null&gt;(null);

  readonly formValue = toSignal(this.form.valueChanges, {
    initialValue: this.form.value,
  });
  readonly formStatus = toSignal(this.form.statusChanges, {
    initialValue: this.form.status,
  });
  readonly isFormValid = computed(() =&gt; this.formStatus() === 'VALID');

  constructor(
    private readonly auth: AuthService,
    private readonly router: Router
  ) {}

  onSubmit() {
    if (!this.isFormValid()) return;

    const { email, password } = this.form.getRawValue();
    if (!email || !password) return;

    this.isLoading.set(true);
    this.errorMessage.set(null);

    this.auth
      .login({ email, password })
      .pipe(take(1))
      .subscribe({
        next: () =&gt; {
          this.isLoading.set(false);
          this.router.navigate(['/welcome']);
        },
        error: (err) =&gt; {
          this.isLoading.set(false);
          const message =
            err?.error?.message ||
            err?.message ||
            'Login failed. Please try again.';
          this.errorMessage.set(message);
        },
      });
  }
}</code></pre>
</div>
</div>
<hr>
</div>
<div class="sect3">
<h4 id="_migration_control_flow_syntax">Migration: Control Flow Syntax</h4>
<div class="quoteblock">
<blockquote>
<div class="paragraph">
<p><strong>Before (classic Angular):</strong></p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-html" data-lang="html">&lt;div *ngIf="loading"&gt;Loading...&lt;/div&gt;
&lt;ul&gt;
  &lt;li *ngFor="let user of users"&gt;{{ user.name }}&lt;/li&gt;
&lt;/ul&gt;</code></pre>
</div>
</div>
<div class="paragraph">
<p><strong>After (Angular 17+):</strong></p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-html" data-lang="html">@if (loading) {
  &lt;div&gt;Loading...&lt;/div&gt;
}
&lt;ul&gt;
  @for (user of users) {
    &lt;li&gt;{{ user.name }}&lt;/li&gt;
  }
&lt;/ul&gt;</code></pre>
</div>
</div>
<div class="ulist">
<ul>
<li>
<p>The new syntax is cleaner and more readable.</p>
</li>
<li>
<p>You can use both during your migration to Angular 17+.</p>
</li>
</ul>
</div>
</blockquote>
</div>
<hr>
</div>
<div class="sect3">
<h4 id="_login_component_html"><code>login.component.html</code></h4>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-html" data-lang="html">&lt;form
  [formGroup]="form"
  (ngSubmit)="onSubmit()"
  class="mt-4 p-4 border rounded shadow-sm bg-white"
  style="max-width: 400px; margin: auto"
&gt;
  &lt;h2 class="text-center mb-4"&gt;Login&lt;/h2&gt;

  &lt;div class="mb-3"&gt;
    @let isInvalidEmail = form.get('email')?.invalid &amp;&amp; form.get('email')?.touched;
    &lt;input
      formControlName="email"
      type="email"
      class="form-control"
      placeholder="Email"
      [class.is-invalid]="isInvalidEmail"
      aria-label="Email"
    /&gt;
    @if (isInvalidEmail) {
      &lt;div class="invalid-feedback"&gt;Please enter a valid email.&lt;/div&gt;
    }
  &lt;/div&gt;

  &lt;div class="mb-3"&gt;
    @let isInvalidPassword = form.get('password')?.invalid &amp;&amp; form.get('password')?.touched;
    &lt;input
      formControlName="password"
      type="password"
      class="form-control"
      placeholder="Password"
      [class.is-invalid]="isInvalidPassword"
      aria-label="Password"
    /&gt;
    @if (isInvalidPassword) {
      &lt;div class="invalid-feedback"&gt;
        Password must be at least 6 characters long.
      &lt;/div&gt;
    }
  &lt;/div&gt;

  @if (errorMessage()) {
    &lt;div class="alert alert-danger"&gt;{{ errorMessage() }}&lt;/div&gt;
  }

  &lt;button
    type="submit"
    class="btn btn-primary w-100"
    [disabled]="isLoading() || !isFormValid()"
  &gt;
    @if (isLoading()) {
      &lt;span class="spinner-border spinner-border-sm me-2"&gt;&lt;/span&gt;
    }
    Login
  &lt;/button&gt;
&lt;/form&gt;</code></pre>
</div>
</div>
<hr>
</div>
</div>
<div class="sect2">
<h3 id="_refactoring_the_register_form">Refactoring the Register Form</h3>
<div class="sect3">
<h4 id="_register_component_ts"><code>register.component.ts</code></h4>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-ts" data-lang="ts">import {
  Component,
  computed,
  signal,
  inject,
  ChangeDetectionStrategy,
} from '@angular/core';
import { Router } from '@angular/router';
import { FormBuilder, Validators, ReactiveFormsModule } from '@angular/forms';
import { AuthService } from '../../services/auth.service';
import { toSignal } from '@angular/core/rxjs-interop';
import { take } from 'rxjs/operators';

@Component({
  selector: 'app-register',
  templateUrl: './register.component.html',
  styleUrls: ['./register.component.scss'],
  standalone: true,
  imports: [ReactiveFormsModule],
  changeDetection: ChangeDetectionStrategy.OnPush,
})
export class RegisterComponent {
  private readonly fb = inject(FormBuilder);
  readonly form = this.fb.group({
    name: ['', [Validators.required]],
    email: ['', [Validators.required, Validators.email]],
    password: ['', [Validators.required, Validators.minLength(6)]],
    role: ['user', [Validators.required]],
  });

  readonly isLoading = signal(false);
  readonly errorMessage = signal&lt;string | null&gt;(null);

  readonly formValue = toSignal(this.form.valueChanges, {
    initialValue: this.form.value,
  });
  readonly formStatus = toSignal(this.form.statusChanges, {
    initialValue: this.form.status,
  });
  readonly isFormValid = computed(() =&gt; this.formStatus() === 'VALID');

  constructor(
    private readonly auth: AuthService,
    private readonly router: Router
  ) {}

  onSubmit() {
    if (!this.isFormValid()) return;

    const { name, email, password, role } = this.form.getRawValue();
    if (!name || !email || !password || !role) return;

    this.isLoading.set(true);
    this.errorMessage.set(null);

    this.auth
      .register({ name, email, password, role })
      .pipe(take(1))
      .subscribe({
        next: () =&gt; {
          this.isLoading.set(false);
          this.router.navigate(['/login']);
        },
        error: (err) =&gt; {
          this.isLoading.set(false);
          const message =
            err?.error?.message ||
            err?.message ||
            'Registration failed. Please try again.';
          this.errorMessage.set(message);
        },
      });
  }
}</code></pre>
</div>
</div>
<hr>
</div>
<div class="sect3">
<h4 id="_register_component_html"><code>register.component.html</code></h4>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-html" data-lang="html">&lt;form
  [formGroup]="form"
  (ngSubmit)="onSubmit()"
  class="mt-4 p-4 border rounded shadow-sm bg-white"
  style="max-width: 400px; margin: auto"
&gt;
  &lt;h2 class="text-center mb-4"&gt;Register&lt;/h2&gt;

  &lt;div class="mb-3"&gt;
    @let isInvalidName = form.get('name')?.invalid &amp;&amp; form.get('name')?.touched;
    &lt;input
      formControlName="name"
      type="text"
      class="form-control"
      placeholder="Name"
      [class.is-invalid]="isInvalidName"
      aria-label="Name"
    /&gt;
    @if (isInvalidName) {
      &lt;div class="invalid-feedback"&gt;Name is required.&lt;/div&gt;
    }
  &lt;/div&gt;

  &lt;div class="mb-3"&gt;
    @let isInvalidEmail = form.get('email')?.invalid &amp;&amp; form.get('email')?.touched;
    &lt;input
      formControlName="email"
      type="email"
      class="form-control"
      placeholder="Email"
      [class.is-invalid]="isInvalidEmail"
      aria-label="Email"
    /&gt;
    @if (isInvalidEmail) {
      &lt;div class="invalid-feedback"&gt;Please enter a valid email.&lt;/div&gt;
    }
  &lt;/div&gt;

  &lt;div class="mb-3"&gt;
    @let isInvalidPassword = form.get('password')?.invalid &amp;&amp; form.get('password')?.touched;
    &lt;input
      formControlName="password"
      type="password"
      class="form-control"
      placeholder="Password"
      [class.is-invalid]="isInvalidPassword"
      aria-label="Password"
    /&gt;
    @if (isInvalidPassword) {
      &lt;div class="invalid-feedback"&gt;
        Password must be at least 6 characters long.
      &lt;/div&gt;
    }
  &lt;/div&gt;

  @if (errorMessage()) {
    &lt;div class="alert alert-danger"&gt;{{ errorMessage() }}&lt;/div&gt;
  }

  &lt;button
    type="submit"
    class="btn btn-success w-100"
    [disabled]="isLoading() || !isFormValid()"
  &gt;
    @if (isLoading()) {
      &lt;span class="spinner-border spinner-border-sm me-2"&gt;&lt;/span&gt;
    }
    Register
  &lt;/button&gt;
&lt;/form&gt;</code></pre>
</div>
</div>
<hr>
</div>
</div>
<div class="sect2">
<h3 id="_real_world_patterns_for_backend_devs">Real-World Patterns for Backend Devs</h3>
<div class="sect3">
<h4 id="_signals_vs_observables">✅ Signals vs Observables</h4>
<div class="quoteblock">
<blockquote>
<div class="paragraph">
<p><strong>Rule of Thumb:</strong> Use signals for local, component-level UI state. Use
observables for async or backend-driven data.</p>
</div>
</blockquote>
</div>
<div class="paragraph">
<p><strong>Signals (local state):</strong></p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-ts" data-lang="ts">isModalOpen = signal(false);

openModal() { this.isModalOpen.set(true); }
closeModal() { this.isModalOpen.set(false); }</code></pre>
</div>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-html" data-lang="html">@if (isModalOpen()) {
  &lt;app-modal (close)="closeModal()"&gt;&lt;/app-modal&gt;
}</code></pre>
</div>
</div>
<div class="paragraph">
<p><strong>Observables (async state):</strong></p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-ts" data-lang="ts">private modalSubject = new BehaviorSubject(false);
isModalOpen$ = this.modalSubject.asObservable();

openModal() { this.modalSubject.next(true); }
closeModal() { this.modalSubject.next(false); }</code></pre>
</div>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-html" data-lang="html">@let isOpen = (isModalOpen$ | async);
@if (isOpen) {
  &lt;app-modal (close)="closeModal()"&gt;&lt;/app-modal&gt;
}</code></pre>
</div>
</div>
<hr>
</div>
<div class="sect3">
<h4 id="_control_flow_in_action">✅ Control Flow in Action</h4>
<div class="paragraph">
<p><strong>Using <code>@for</code> instead of <code>*ngFor</code>:</strong></p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-html" data-lang="html">&lt;ul&gt;
  @for (user of users; track user.id) {
    &lt;li&gt;{{ user.name }}&lt;/li&gt;
  }
&lt;/ul&gt;</code></pre>
</div>
</div>
<div class="paragraph">
<p><strong>Using <code>@switch</code> vs <code>*ngSwitch</code>:</strong></p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-html" data-lang="html">@switch (status) {
  @case ('loading') {
    &lt;p&gt;Loading...&lt;/p&gt;
  } @case ('error') {
    &lt;p&gt;Error!&lt;/p&gt;
  } @default {
    &lt;p&gt;All good.&lt;/p&gt;
  }
}</code></pre>
</div>
</div>
<div class="quoteblock">
<blockquote>
<div class="paragraph">
<p><strong>Backend parallel:</strong> <code>@if</code>, <code>@for</code>, and <code>@switch</code> are like inline logic
in your backend template engines (e.g., EJS, Razor, Thymeleaf)—but here
they’re fully reactive and type-safe.</p>
</div>
</blockquote>
</div>
<hr>
</div>
<div class="sect3">
<h4 id="_lazy_loading_and_ux_patterns_with_defer">✅ Lazy Loading and UX Patterns with @defer</h4>
<div class="paragraph">
<p>Angular’s <code>@defer</code> block is great for loading UI only when needed.</p>
</div>
<div class="paragraph">
<p><strong>Basic Usage:</strong></p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-html" data-lang="html">@defer (when isHeavyComponentVisible) {
  &lt;app-heavy-widget&gt;&lt;/app-heavy-widget&gt;
} @placeholder {
  &lt;p&gt;Loading widget...&lt;/p&gt;
}</code></pre>
</div>
</div>
<div class="paragraph">
<p><strong>Loading feedback:</strong></p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-html" data-lang="html">@defer (when dataReady; loading minimum 300ms) {
  &lt;app-dashboard&gt;&lt;/app-dashboard&gt;
} @loading {
  &lt;p&gt;Loading dashboard...&lt;/p&gt;
} @placeholder {
  &lt;p&gt;Initializing view...&lt;/p&gt;
}</code></pre>
</div>
</div>
<div class="paragraph">
<p><strong>Viewport entry:</strong></p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-html" data-lang="html">@defer (on viewport) {
  &lt;app-news-feed&gt;&lt;/app-news-feed&gt;
} @placeholder {
  &lt;p&gt;Loading news feed when visible...&lt;/p&gt;
}</code></pre>
</div>
</div>
<div class="paragraph">
<p><strong>Idle trigger:</strong></p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-html" data-lang="html">@defer (on idle) {
  &lt;app-recommendations&gt;&lt;/app-recommendations&gt;
}</code></pre>
</div>
</div>
<div class="quoteblock">
<blockquote>
<div class="paragraph">
<p>⏳ <strong>Why care?</strong> Optimizes TTI (time to interactive) on heavy or mobile
pages.</p>
</div>
</blockquote>
</div>
<hr>
</div>
<div class="sect3">
<h4 id="_smart_change_detection_in_a_dashboard">✅ Smart Change Detection in a Dashboard</h4>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-ts" data-lang="ts">userCount = signal(0);
orderTotal = signal(0);

ngOnInit() {
  this.api.getUsers().subscribe(users =&gt; this.userCount.set(users.length));
  this.api.getOrders().subscribe(orders =&gt; this.orderTotal.set(orders.length));
}</code></pre>
</div>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-html" data-lang="html">&lt;div&gt;Users: {{ userCount() }}&lt;/div&gt;
&lt;div&gt;Orders: {{ orderTotal() }}&lt;/div&gt;</code></pre>
</div>
</div>
<div class="quoteblock">
<blockquote>
<div class="paragraph">
<p><strong>Signals update just what changed—no wasted DOM re-renders.</strong></p>
</div>
</blockquote>
</div>
<hr>
</div>
</div>
<div class="sect2">
<h3 id="_ssr_hydration_bonus_note">SSR &amp; Hydration (Bonus Note)</h3>
<div class="paragraph">
<p>💡 <em>SSR &amp; Hydration</em>: Angular 19’s hydration improvements are especially
useful if you’re rendering Angular on the server (Angular Universal).
Most projects won’t need this—but it’s a great step for future-proofing.</p>
</div>
<hr>
</div>
<div class="sect2">
<h3 id="_final_thoughts">Final Thoughts</h3>
<div class="paragraph">
<p>Angular 19 brings a more approachable and modern developer experience: signals simplify state, <code>@if</code> and <code>@for</code> make templates more readable, and <code>@defer</code> gives you fine control over performance.</p>
</div>
<div class="paragraph">
<p><strong>You just:</strong></p>
</div>
<div class="ulist">
<ul>
<li>
<p>Replaced legacy form logic with clean Signals-based state.</p>
</li>
<li>
<p>Simplified templates using Angular’s new control flow.</p>
</li>
<li>
<p>Learned how to delay rendering and optimize performance with <code>@defer</code>.</p>
</li>
</ul>
</div>
<div class="paragraph">
<p><strong>Next:</strong> We’ll bring everything together in Part 5 with route guards,
token parsing, and role-based access control.</p>
</div>
<hr>
<div class="sect3">
<h4 id="_further_reading">Further Reading</h4>
<div class="ulist">
<ul>
<li>
<p><a href="https://angular.dev">Angular 19 Signals Guide (angular.dev)</a></p>
</li>
<li>
<p><a href="https://angular.dev/reference/forms/using-signals">Reactive Forms
vs. Signals—How to Choose</a></p>
</li>
</ul>
</div>
</div>
</div>
<]]></content:encoded>
					
		
		
			</item>
         
	<item>
		<title>Part 3: Frontend Setup with Angular</title>
		<link>https://blog.lunatech.com//posts/2025-05-06-part-3%3A-frontend-setup-with-angular</link>
		
		<dc:creator><![CDATA[Jake Ortega]]></dc:creator>
        <pubDate>2025-05-06T00:00:00.000Z</pubDate>
         
             {
            <category><![CDATA[angular]]></category>
                }
             {
            <category><![CDATA[nestjs]]></category>
                }
             {
            <category><![CDATA[postgresql]]></category>
                }
             {
            <category><![CDATA[typeorm]]></category>
                }
             {
            <category><![CDATA[jwt]]></category>
                }
             {
            <category><![CDATA[authentication]]></category>
                }
             {
            <category><![CDATA[frontend]]></category>
                }
             {
            <category><![CDATA[typescript]]></category>
                }
             {
            <category><![CDATA[nodejs]]></category>
                }
             {
            <category><![CDATA[en]]></category>
                }
             
        
		<guid isPermaLink="false">https://blog.lunatech.com//posts/2025-05-06-part-3%3A-frontend-setup-with-angular</guid>

					<description>
                        <![CDATA[ Now that we’ve built our NestJS backend with secure JWT auth, it’s time]]></description>
                    <content:encoded><![CDATA[
                    <div id="preamble">
<div class="sectionbody">
<div class="paragraph">
<p>Now that we’ve built our NestJS backend with secure JWT auth, it’s time
to wire up the frontend. In this part, we’ll scaffold an <strong>Angular</strong> app,
integrate it with our backend, and secure it with <strong>JWT-based route
protection</strong>.</p>
</div>
<div class="paragraph">
<p>By the end of this part, you’ll have:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>A basic Angular app styled with Bootstrap</p>
</li>
<li>
<p>Auth service for login/register with JWT handling</p>
</li>
<li>
<p>Login and Register components using reactive forms</p>
</li>
<li>
<p>A protected Welcome page</p>
</li>
<li>
<p>Route guard to lock down private views</p>
</li>
</ul>
</div>
<hr>
</div>
</div>
<div class="sect2">
<h3 id="_step_1_initialize_the_angular_frontend"><strong>Step 1: Initialize the Angular Frontend</strong></h3>
<div class="paragraph">
<p>Let’s get your frontend up and running. Open your terminal and run:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-bash" data-lang="bash">ng new frontend
cd frontend</code></pre>
</div>
</div>
<div class="paragraph">
<p>Pick SCSS (or your favorite style option) when prompted.<br>
This gives you a fresh Angular workspace to play with.</p>
</div>
<div class="sect3">
<h4 id="_what_is_ng_in_angular_cli">What is <code>ng</code> in Angular CLI?</h4>
<div class="paragraph">
<p>The <code>ng</code> command is the core of the Angular CLI (Command Line Interface)
— a powerful toolkit that streamlines Angular development from start to
finish. It acts as a shortcut to perform a wide range of tasks without
manually setting up files or configurations.</p>
</div>
<div class="paragraph">
<p>With <code>ng</code>, you can quickly scaffold new projects, generate application
features, and manage your build and development workflow with ease. Here
are some common <code>ng</code> commands and what they do:</p>
</div>
<div class="ulist">
<ul>
<li>
<p><code>ng new</code>: Creates a new Angular project with a complete directory
structure, TypeScript configuration, and ready-to-run setup.</p>
</li>
<li>
<p><code>ng generate</code> (or <code>ng g</code>): Automatically creates Angular building
blocks such as components, services, directives, pipes, and more —
following Angular’s style guide and best practices.</p>
</li>
<li>
<p><code>ng serve</code>: Launches a local development server with live reload. As
you make changes, the app updates instantly in the browser.</p>
</li>
<li>
<p><code>ng build</code>: Compiles your application into optimized static files for
production deployment.</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>The real power of <code>ng</code> lies in automation. It eliminates repetitive
boilerplate and helps you stick to Angular conventions, leading to
cleaner, more maintainable codebases.</p>
</div>
<div class="quoteblock">
<blockquote>
<div class="paragraph">
<p>💡 <strong>Tip:</strong> With Angular v19, components and services are created as
<strong>standalone</strong> by default. This means they no longer need to be declared
in NgModules, which promotes better modularity and reduces coupling in
your app architecture.</p>
</div>
</blockquote>
</div>
<div class="paragraph">
<p>By mastering the <code>ng</code> CLI, you’re not just saving time — you’re building
apps the Angular way, with a foundation rooted in scalability and
consistency.</p>
</div>
<hr>
</div>
</div>
<div class="sect2">
<h3 id="_step_2_install_dependencies"><strong>Step 2: Install Dependencies</strong></h3>
<div class="paragraph">
<p>We’ll need a few extras to make our app functional and visually
appealing:</p>
</div>
<div class="ulist">
<ul>
<li>
<p><strong>Bootstrap</strong>: For responsive and professional styling.</p>
</li>
<li>
<p><strong>jwt-decode</strong>: To decode JWTs and extract user information.</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>Install them with:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-bash" data-lang="bash">npm install bootstrap jwt-decode</code></pre>
</div>
</div>
<hr>
</div>
<div class="sect2">
<h3 id="_step_3_set_up_bootstrap"><strong>Step 3: Set Up Bootstrap</strong></h3>
<div class="paragraph">
<p>Let’s make things look good with minimal effort.</p>
</div>
<div class="olist arabic">
<ol class="arabic">
<li>
<p>Open <code>angular.json</code></p>
</li>
<li>
<p>Find the <code>"styles"</code> array and add Bootstrap’s CSS:</p>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-json" data-lang="json">"styles": [
  "node_modules/bootstrap/dist/css/bootstrap.min.css",
  "src/styles.scss"
]</code></pre>
</div>
</div>
</li>
<li>
<p>Start your development server if it’s not already running:</p>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-bash" data-lang="bash">ng serve</code></pre>
</div>
</div>
</li>
</ol>
</div>
<div class="paragraph">
<p>Test it by adding a Bootstrap class (like <code>btn btn-primary</code>) to a button
in <code>app.component.html</code>. If it’s blue, you’re golden.</p>
</div>
<hr>
</div>
<div class="sect2">
<h3 id="_step_4_setting_up_environments"><strong>Step 4: Setting Up Environments</strong></h3>
<div class="paragraph">
<p>Angular provides a built-in way to manage environment-specific
configurations, such as API URLs for development and production. Let’s
configure them.</p>
</div>
<div class="olist arabic">
<ol class="arabic">
<li>
<p>Run the following command to generate the environment files for
development and production:</p>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-bash" data-lang="bash">ng generate environments</code></pre>
</div>
</div>
<div class="paragraph">
<p>This will create two files in the <code>src/environments/</code> folder:</p>
</div>
<div class="literalblock">
<div class="content">
<pre>src/
├── environments/
│   ├── environment.development.ts # Development environment
│   └── environment.ts             # Production environment</pre>
</div>
</div>
</li>
<li>
<p>Open both <code>environment.ts</code> and <code>environment.development.ts</code> and add
the <code>apiUrl</code> property. <code>environment.development.ts</code></p>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-typescript" data-lang="typescript">export const environment = {
  production: false,
  apiUrl: "http://localhost:3000", // Replace with your backend's dev URL
};</code></pre>
</div>
</div>
<div class="paragraph">
<p><code>environment.ts</code></p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-typescript" data-lang="typescript">export const environment = {
  production: true,
  apiUrl: "https://your-production-api.com", // Replace with your backend's prod URL
};</code></pre>
</div>
</div>
</li>
<li>
<p>The <code>environment</code> files are automatically selected based on the build
configuration:</p>
<div class="ulist">
<ul>
<li>
<p><strong>Development</strong>: When running <code>ng serve</code>, Angular replaces
<code>environment.ts</code> with <code>environment.development.ts</code>.</p>
</li>
<li>
<p><strong>Production</strong>: when running <code>ng build --prod</code>, Angular uses
<code>environment.ts</code>.</p>
<div class="paragraph">
<p>You can now use <code>environment.apiUrl</code> in your services to dynamically
switch between development and production APIs.</p>
</div>
</li>
</ul>
</div>
</li>
</ol>
</div>
<hr>
</div>
<div class="sect2">
<h3 id="_step_5_generate_guards_services_and_components"><strong>Step 5: Generate Guards, Services, and Components</strong></h3>
<div class="paragraph">
<p>Let Angular CLI do the heavy lifting for you. Run the following commands
to generate the necessary files:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-bash" data-lang="bash">ng generate service services/auth
ng generate guard auth/auth
ng generate component pages/login
ng generate component pages/register
ng generate component pages/welcome</code></pre>
</div>
</div>
<div class="paragraph">
<p>What These Commands Do:</p>
</div>
<div class="olist arabic">
<ol class="arabic">
<li>
<p><strong>Auth Service</strong>: Handles API calls for login, registration, and token
management.</p>
</li>
<li>
<p><strong>Auth Guard</strong>: Protects routes by checking if the user is
authenticated.</p>
</li>
<li>
<p><strong>Login Component</strong>: Provides a form for users to log in.</p>
</li>
<li>
<p><strong>Register Component</strong>: Provides a form for users to register.</p>
</li>
<li>
<p><strong>Welcome Component</strong>: Displays a personalized welcome message for
logged-in users.</p>
</li>
</ol>
</div>
<div class="paragraph">
<p>This sets up your folders and boilerplate files, keeping things
organized and modular.</p>
</div>
<div class="sect3">
<h4 id="_project_structure_overview">Project Structure Overview</h4>
<div class="paragraph">
<p>Here’s how your Angular app should look after generating the files:</p>
</div>
<div class="literalblock">
<div class="content">
<pre>src/
├── app/
│   ├── auth/                     # Guards, interceptors, maybe a module
│   │   └── auth.guard.ts
│   ├── pages/                    # Feature components
│   │   ├── login/
│   │   │   ├── login.component.html
│   │   │   ├── login.component.scss
│   │   │   └── login.component.ts
│   │   ├── register/
│   │   │   ├── register.component.html
│   │   │   ├── register.component.scss
│   │   │   └── register.component.ts
│   │   └── welcome/
│   │       ├── welcome.component.html
│   │       ├── welcome.component.scss
│   │       └── welcome.component.ts
│   ├── services/                 # API communication
│   │   └── auth.service.ts
│   ├── shared/                   # Models, utilities, etc. (optional)
│   ├── app.component.html
│   ├── app.component.scss
│   ├── app.component.ts
│   ├── app.config.ts
│   └── app.routes.ts
├── environments/
│   ├── environment.development.ts # Development environment
│   └── environment.ts             # Production environment
├── index.html
├── main.ts
└── style.scss</pre>
</div>
</div>
<hr>
</div>
</div>
<div class="sect2">
<h3 id="_step_6_the_auth_service_your_api_bridge"><strong>Step 6: The Auth Service – Your API Bridge</strong></h3>
<div class="paragraph">
<p>The <code>AuthService</code> is the backbone of your authentication flow. It
communicates with your backend’s <code>/auth/login</code> and <code>/auth/register</code>
endpoints, manages the JWT in localStorage, and provides utility methods
for token handling.</p>
</div>
<div class="paragraph">
<p>Here’s the complete implementation:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-typescript" data-lang="typescript">// src/app/services/auth.service.ts
import { Injectable } from "@angular/core";
import { HttpClient } from "@angular/common/http";
import { catchError, Observable, tap, throwError } from "rxjs";
import { environment } from "../../environments/environment";

@Injectable({
  providedIn: "root",
})
export class AuthService {
  constructor(private http: HttpClient) {}

  /**
   * Logs in the user by sending their credentials to the backend.
   * Stores the access token in localStorage upon success.
   * @param data - The user's email and password.
   * @returns An observable containing the access token.
   */
  login(data: {
    email: string;
    password: string;
  }): Observable&lt;{ access_token: string }&gt; {
    return this.http
      .post&lt;{ access_token: string }&gt;(`${environment.apiUrl}/auth/login`, data)
      .pipe(
        tap((res) =&gt; localStorage.setItem("access_token", res.access_token)),
        catchError((error) =&gt; {
          const errorMessage =
            error.status === 401
              ? "Invalid email or password. Please try again."
              : "An unexpected error occurred. Please try again later.";
          return throwError(() =&gt; new Error(errorMessage));
        })
      );
  }

  /**
   * Registers a new user by sending their details to the backend.
   * @param data - The user's name, email, password, and role.
   * @returns An observable for the registration process.
   */
  register(data: {
    email: string;
    password: string;
    name: string;
    role: string;
  }): Observable&lt;any&gt; {
    return this.http.post(`${environment.apiUrl}/auth/register`, data).pipe(
      catchError((error) =&gt; {
        const errorMessage =
          error.status === 400
            ? "Registration failed. Please check your input."
            : "An unexpected error occurred. Please try again later.";
        return throwError(() =&gt; new Error(errorMessage));
      })
    );
  }

  /**
   * Logs out the user by removing the access token from localStorage.
   */
  logout(): void {
    localStorage.removeItem("access_token");
  }

  /**
   * Retrieves the stored access token from localStorage.
   * @returns The access token or null if not found.
   */
  getToken(): string | null {
    return localStorage.getItem("access_token");
  }

  /**
   * Checks if the user is authenticated by verifying the presence of a token.
   * @returns A boolean indicating whether the user is authenticated.
   */
  isAuthenticated(): boolean {
    const token = this.getToken();
    return !!token;
  }
}</code></pre>
</div>
</div>
<hr>
</div>
<div class="sect2">
<h3 id="_step_7_protecting_routes_with_a_guard"><strong>Step 7: Protecting Routes with a Guard</strong></h3>
<div class="paragraph">
<p>Angular’s <code>CanActivate</code> guard is like a backend middleware for your
routes. Here’s how we check for a valid JWT:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-typescript" data-lang="typescript">// src/app/auth/auth.guard.ts
import { Injectable } from "@angular/core";
import { CanActivate, Router } from "@angular/router";
import { AuthService } from "../services/auth.service";
import { jwtDecode } from "jwt-decode";

@Injectable({ providedIn: "root" })
export class AuthGuard implements CanActivate {
  constructor(private authService: AuthService, private router: Router) {}

  canActivate(): boolean {
    const token = this.authService.getToken();
    if (!token) {
      this.redirectToLogin();
      return false;
    }

    if (this.isTokenExpired(token)) {
      this.authService.logout();
      this.redirectToLogin();
      return false;
    }

    return true;
  }

  /**
   * Checks if the token is expired.
   * @param token - The JWT token to validate.
   * @returns A boolean indicating whether the token is expired.
   */
  private isTokenExpired(token: string): boolean {
    try {
      const decoded: any = jwtDecode(token);
      return Date.now() &gt; decoded.exp * 1000;
    } catch {
      return true; // Treat invalid tokens as expired
    }
  }

  /**
   * Redirects the user to the login page.
   */
  private redirectToLogin(): void {
    this.router.navigate(["/login"]);
  }
}</code></pre>
</div>
</div>
<hr>
</div>
<div class="sect2">
<h3 id="_step_8_login_register_components"><strong>Step 8: Login &amp; Register Components</strong></h3>
<div class="paragraph">
<p>The <code>LoginComponent</code> and <code>RegisterComponent</code> are the core components for
user authentication in the application. Both components use Angular’s
reactive forms to manage user input and validations. They interact with
the <code>AuthService</code> to send requests to the backend for login and
registration functionality. Upon successful operations, they navigate
the user to the appropriate page (<code>/welcome</code> for login and <code>/login</code> for
registration).</p>
</div>
<div class="paragraph">
<p>Key Features</p>
</div>
<div class="ulist">
<ul>
<li>
<p><strong>Reactive Forms</strong>: Both components use Angular’s reactive forms to
handle user input and validations.</p>
</li>
<li>
<p><strong>Validation Rules</strong>: Fields like <code>email</code>, <code>password</code>, and <code>name</code> (for
registration) have validation rules to ensure proper input.</p>
</li>
<li>
<p><strong>Error Handling</strong>: User-friendly error messages are displayed when
login or registration fails.</p>
</li>
<li>
<p><strong>Loading State</strong>: Prevents duplicate submissions by disabling the
submit button while the request is in progress.</p>
</li>
<li>
<p><strong>Navigation</strong>: Redirects users to the appropriate page upon successful
login or registration.</p>
</li>
</ul>
</div>
<hr>
<div class="olist arabic">
<ol class="arabic">
<li>
<p><strong>Login Component</strong></p>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-typescript" data-lang="typescript">// src/app/pages/login/login.component.ts
import { Component } from "@angular/core";
import { Router } from "@angular/router";
import {
  FormBuilder,
  FormGroup,
  ReactiveFormsModule,
  Validators,
} from "@angular/forms";
import { AuthService } from "../../services/auth.service";
import { CommonModule } from "@angular/common";

@Component({
  selector: "app-login",
  templateUrl: "./login.component.html",
  styleUrls: ["./login.component.scss"],
  imports: [ReactiveFormsModule, CommonModule],
})
export class LoginComponent {
  form: FormGroup;
  isLoading = false;
  errorMessage: string | null = null;

  constructor(
    private fb: FormBuilder,
    private auth: AuthService,
    private router: Router
  ) {
    this.form = this.fb.group({
      email: ["", [Validators.required, Validators.email]],
      password: ["", [Validators.required, Validators.minLength(6)]],
    });
  }

  onSubmit() {
    if (this.form.invalid) return;

    this.isLoading = true;
    this.errorMessage = null;

    this.auth.login(this.form.value).subscribe({
      next: () =&gt; {
        this.isLoading = false;
        this.router.navigate(["/welcome"]);
      },
      error: (err) =&gt; {
        this.isLoading = false;
        this.errorMessage =
          err.error?.message || "Login failed. Please try again.";
      },
    });
  }
}</code></pre>
</div>
</div>
</li>
<li>
<p><strong>Login HTML</strong></p>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-html" data-lang="html">&lt;!-- src/app/pages/login/login.component.html --&gt;
&lt;form
  [formGroup]="form"
  (ngSubmit)="onSubmit()"
  class="mt-4 p-4 border rounded shadow-sm bg-white"
  style="max-width: 400px; margin: auto"
&gt;
  &lt;h2 class="text-center mb-4"&gt;Login&lt;/h2&gt;

  &lt;div class="mb-3"&gt;
    &lt;input
      formControlName="email"
      type="email"
      class="form-control"
      placeholder="Email"
      [class.is-invalid]="
        form.get('email')?.invalid &amp;&amp; form.get('email')?.touched
      "
      aria-label="Email"
    /&gt;
    &lt;div
      *ngIf="form.get('email')?.invalid &amp;&amp; form.get('email')?.touched"
      class="invalid-feedback"
    &gt;
      Please enter a valid email.
    &lt;/div&gt;
  &lt;/div&gt;

  &lt;div class="mb-3"&gt;
    &lt;input
      formControlName="password"
      type="password"
      class="form-control"
      placeholder="Password"
      [class.is-invalid]="
        form.get('password')?.invalid &amp;&amp; form.get('password')?.touched
      "
      aria-label="Password"
    /&gt;
    &lt;div
      *ngIf="form.get('password')?.invalid &amp;&amp; form.get('password')?.touched"
      class="invalid-feedback"
    &gt;
      Password must be at least 6 characters long.
    &lt;/div&gt;
  &lt;/div&gt;

  &lt;div *ngIf="errorMessage" class="alert alert-danger"&gt;
    {{ errorMessage }}
  &lt;/div&gt;

  &lt;button type="submit" class="btn btn-primary w-100" [disabled]="isLoading"&gt;
    &lt;span
      *ngIf="isLoading"
      class="spinner-border spinner-border-sm me-2"
    &gt;&lt;/span&gt;
    Login
  &lt;/button&gt;
&lt;/form&gt;</code></pre>
</div>
</div>
</li>
<li>
<p><strong>Register Component</strong></p>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-typescript" data-lang="typescript">// src/app/pages/register/register.component.ts
import { Component } from "@angular/core";
import { Router } from "@angular/router";
import {
  FormBuilder,
  FormGroup,
  ReactiveFormsModule,
  Validators,
} from "@angular/forms";
import { AuthService } from "../../services/auth.service";
import { CommonModule } from "@angular/common";

@Component({
  selector: "app-register",
  templateUrl: "./register.component.html",
  styleUrls: ["./register.component.scss"],
  imports: [ReactiveFormsModule, CommonModule],
})
export class RegisterComponent {
  form: FormGroup;
  isLoading = false;
  errorMessage: string | null = null;

  constructor(
    private fb: FormBuilder,
    private auth: AuthService,
    private router: Router
  ) {
    this.form = this.fb.group({
      name: ["", [Validators.required]],
      email: ["", [Validators.required, Validators.email]],
      password: ["", [Validators.required, Validators.minLength(6)]],
      role: ["user", [Validators.required]],
    });
  }

  onSubmit() {
    if (this.form.invalid) return;

    this.isLoading = true;
    this.errorMessage = null;

    this.auth.register(this.form.value).subscribe({
      next: () =&gt; {
        this.isLoading = false;
        this.router.navigate(["/login"]);
      },
      error: (err) =&gt; {
        this.isLoading = false;
        this.errorMessage =
          err.error?.message || "Registration failed. Please try again.";
      },
    });
  }
}</code></pre>
</div>
</div>
</li>
<li>
<p><strong>Register HTML</strong></p>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-html" data-lang="html">&lt;form
  [formGroup]="form"
  (ngSubmit)="onSubmit()"
  class="mt-4 p-4 border rounded shadow-sm bg-white"
  style="max-width: 400px; margin: auto"
&gt;
  &lt;h2 class="text-center mb-4"&gt;Register&lt;/h2&gt;

  &lt;div class="mb-3"&gt;
    &lt;input
      formControlName="name"
      type="text"
      class="form-control"
      placeholder="Name"
      [class.is-invalid]="
         form.get('name')?.invalid &amp;&amp; form.get('name')?.touched
       "
      aria-label="Name"
    /&gt;
    &lt;div
      *ngIf="form.get('name')?.invalid &amp;&amp; form.get('name')?.touched"
      class="invalid-feedback"
    &gt;
      Name is required.
    &lt;/div&gt;
  &lt;/div&gt;

  &lt;div class="mb-3"&gt;
    &lt;input
      formControlName="email"
      type="email"
      class="form-control"
      placeholder="Email"
      [class.is-invalid]="
         form.get('email')?.invalid &amp;&amp; form.get('email')?.touched
       "
      aria-label="Email"
    /&gt;
    &lt;div
      *ngIf="form.get('email')?.invalid &amp;&amp; form.get('email')?.touched"
      class="invalid-feedback"
    &gt;
      Please enter a valid email.
    &lt;/div&gt;
  &lt;/div&gt;

  &lt;div class="mb-3"&gt;
    &lt;input
      formControlName="password"
      type="password"
      class="form-control"
      placeholder="Password"
      [class.is-invalid]="
         form.get('password')?.invalid &amp;&amp; form.get('password')?.touched
       "
      aria-label="Password"
    /&gt;
    &lt;div
      *ngIf="form.get('password')?.invalid &amp;&amp; form.get('password')?.touched"
      class="invalid-feedback"
    &gt;
      Password must be at least 6 characters long.
    &lt;/div&gt;
  &lt;/div&gt;

  &lt;div *ngIf="errorMessage" class="alert alert-danger"&gt;
    {{ errorMessage }}
  &lt;/div&gt;

  &lt;button type="submit" class="btn btn-success w-100" [disabled]="isLoading"&gt;
    &lt;span
      *ngIf="isLoading"
      class="spinner-border spinner-border-sm me-2"
    &gt;&lt;/span&gt;
    Register
  &lt;/button&gt;
&lt;/form&gt;</code></pre>
</div>
</div>
</li>
</ol>
</div>
<hr>
</div>
<div class="sect2">
<h3 id="_step_9_welcome_page_static_greeting_and_logout"><strong>Step 9: Welcome Page – Static Greeting and Logout</strong></h3>
<div class="paragraph">
<p>The <code>WelcomeComponent</code> provides a user-friendly page that welcomes the
user after a successful login. It integrates with the existing
AuthService to manage logout functionality but does not attempt to
decode or extract any user-specific data from the access token.</p>
</div>
<div class="paragraph">
<p>Key Features</p>
</div>
<div class="ulist">
<ul>
<li>
<p><strong>Static Greeting</strong>: Display a generic welcome message for all users.</p>
</li>
<li>
<p><strong>Logout Functionality</strong>: Allow users to log out and clear their
session.</p>
</li>
</ul>
</div>
<hr>
<div class="olist arabic">
<ol class="arabic">
<li>
<p><strong>Welcome Component</strong></p>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-typescript" data-lang="typescript">// src/app/pages/welcome/welcome.component.ts
import { Component } from "@angular/core";
import { AuthService } from "../../services/auth.service";
import { Router } from "@angular/router";

@Component({
  selector: "app-welcome",
  templateUrl: "./welcome.component.html",
  styleUrls: ["./welcome.component.scss"],
})
export class WelcomeComponent {
  constructor(private authService: AuthService, private router: Router) {}

  logout(): void {
    this.authService.logout();
    this.router.navigate(["/login"]);
  }
}</code></pre>
</div>
</div>
</li>
<li>
<p><strong>Welcome HTML</strong></p>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-html" data-lang="html">&lt;!-- src/app/pages/welcome/welcome.component.html --&gt;
&lt;div class="welcome-container text-center mt-5"&gt;
  &lt;h1 class="display-4"&gt;Welcome!&lt;/h1&gt;
  &lt;p class="lead"&gt;We're glad to have you here.&lt;/p&gt;
  &lt;button class="btn btn-primary mt-3" (click)="logout()"&gt;Logout&lt;/button&gt;
&lt;/div&gt;</code></pre>
</div>
</div>
</li>
<li>
<p><strong>Welcome Component SCSS</strong></p>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-scss" data-lang="scss">/* /src/app/pages/welcome/welcome.component.scss */
.welcome-container {
  max-width: 600px;
  margin: auto;
  padding: 20px;
  background-color: #f8f9fa;
  border-radius: 8px;
  box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
}

h1 {
  color: #343a40;
}

p {
  color: #6c757d;
}</code></pre>
</div>
</div>
</li>
</ol>
</div>
<hr>
</div>
<div class="sect2">
<h3 id="_step_10_routing_lock_down_protected_pages"><strong>Step 10: Routing: Lock Down Protected Pages</strong></h3>
<div class="paragraph">
<p>Alright, now that we’ve got our login, registration, and welcome pages
ready, it’s time to lock things down. We don’t want just anyone
accessing the protected parts of our app, right? That’s where Angular’s
routing and guards come into play. Let’s set up our routes and ensure
only authenticated users can access the welcome page.</p>
</div>
<div class="sect3">
<h4 id="_setting_up_routes">Setting Up Routes</h4>
<div class="paragraph">
<p>In Angular, routes define how users navigate through your app. Here’s
how we’ll structure our routes:</p>
</div>
<div class="ulist">
<ul>
<li>
<p><code>/login</code>: For users to log in.</p>
</li>
<li>
<p><code>/register</code>: For new users to sign up.</p>
</li>
<li>
<p><code>/welcome</code>: A protected page that greets logged-in users.</p>
</li>
<li>
<p><code>/</code>: Redirects to <code>/welcome</code> by default.</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>Here’s the code:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-typescript" data-lang="typescript">// src/app/app.routes.ts
import { Routes } from "@angular/router";
import { LoginComponent } from "./pages/login/login.component";
import { RegisterComponent } from "./pages/register/register.component";
import { WelcomeComponent } from "./pages/welcome/welcome.component";
import { AuthGuard } from "./auth/auth.guard";

export const routes: Routes = [
  { path: "", redirectTo: "welcome", pathMatch: "full" },
  { path: "login", component: LoginComponent },
  { path: "register", component: RegisterComponent },
  { path: "welcome", component: WelcomeComponent, canActivate: [AuthGuard] },
];</code></pre>
</div>
</div>
<div class="paragraph">
<p>This is a simple and clean way to define your app’s navigation. Notice
how we’ve added <code>canActivate: [AuthGuard]</code> to the <code>/welcome</code> route?
That’s the magic that protects it.</p>
</div>
</div>
<div class="sect3">
<h4 id="_protecting_routes_with_a_guard">Protecting Routes with a Guard</h4>
<div class="paragraph">
<p>The <code>AuthGuard</code> is like a bouncer for your routes. It checks if the user
is authenticated before letting them in. If they’re not, it redirects
them to the login page.</p>
</div>
</div>
<div class="sect3">
<h4 id="_wiring_it_all_together">Wiring It All Together</h4>
<div class="paragraph">
<p>Now that we’ve defined our routes and guard, let’s hook everything up in
<code>main.ts</code>. Angular v19 makes this super simple with the <code>provideRouter</code>
function:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-typescript" data-lang="typescript">// src/main.ts
import { bootstrapApplication } from "@angular/platform-browser";
import { AppComponent } from "./app/app.component";
import { provideRouter } from "@angular/router";
import { routes } from "./app/app.routes";
import { provideHttpClient } from "@angular/common/http";

bootstrapApplication(AppComponent, {
  providers: [
    provideRouter(routes), // Provide the routes
    provideHttpClient(), // Provide the HTTP client
  ],
}).catch((err) =&gt; console.error(err));</code></pre>
</div>
</div>
<div class="paragraph">
<p>No need for a separate <code>AppRoutingModule</code>. Just provide the routes
directly in <code>main.ts</code>, and you’re good to go.</p>
</div>
</div>
<div class="sect3">
<h4 id="_testing_it_out">Testing It Out</h4>
<div class="olist arabic">
<ol class="arabic">
<li>
<p><strong>Try Accessing <code>/welcome</code> Without Logging In</strong>:</p>
<div class="ulist">
<ul>
<li>
<p>You should be redirected to <code>/login</code>.</p>
</li>
</ul>
</div>
</li>
<li>
<p><strong>Log In and Access <code>/welcome</code></strong>:</p>
<div class="ulist">
<ul>
<li>
<p>After logging in, navigate to <code>/welcome</code>. You should see the
personalized greeting.</p>
</li>
</ul>
</div>
</li>
<li>
<p><strong>Log Out and Try Again</strong>:</p>
<div class="ulist">
<ul>
<li>
<p>After logging out, try accessing <code>/welcome</code> again. You should be
redirected to <code>/login</code>.</p>
</li>
</ul>
</div>
</li>
</ol>
</div>
</div>
<div class="sect3">
<h4 id="_why_this_matters">Why This Matters</h4>
<div class="paragraph">
<p>For backend developers, this should feel familiar. Think of the
<code>AuthGuard</code> as middleware for your routes. It ensures that only
authenticated users can access certain parts of your app, just like how
you’d protect API endpoints on the server side.</p>
</div>
<div class="paragraph">
<p>By combining Angular’s routing with guards, you’ve got a solid
foundation for building secure, user-friendly apps. And the best part?
It’s modular and easy to extend. Want to add role-based access? Just
tweak the guard. Need to protect more routes? Add <code>canActivate</code> to them.</p>
</div>
<hr>
</div>
</div>
<div class="sect2">
<h3 id="_whats_next"><strong>What’s Next?</strong></h3>
<div class="paragraph">
<p>You’ve got a working Angular app wired to your backend, protected with
route guards and powered by JWT auth. Next up, we’ll level things up
with some Angular 19 enhancements and best practices.</p>
</div>
<div class="paragraph">
<p>👉 <strong>Part 4: Angular 19 Deep Dive</strong></p>
</div>
<div class="paragraph">
<p>We’ll cover:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>🧠 <strong>Signals vs Observables</strong> — When to use which and why</p>
</li>
<li>
<p>🔁 <code>@if</code>, <code>@for</code>, and <code>defer</code> blocks — Smarter templates with better
control</p>
</li>
<li>
<p>⚡ <strong>Change detection and performance tuning</strong></p>
</li>
</ul>
</div>
<div class="paragraph">
<p>This part’s optional, but worth it if you want your Angular app to be
leaner, faster, and future-ready.</p>
</div>
<div class="paragraph">
<p>For now, pat yourself on the back—you’ve just implemented a secure,
modern routing system in Angular. 🚀</p>
</div>
</div>
<]]></content:encoded>
					
		
		
			</item>
         
	<item>
		<title>AI plugins for code development</title>
		<link>https://blog.lunatech.com//posts/2025-05-02-ai-plugins-for-code-development</link>
		
		<dc:creator><![CDATA[Rajendra Maniyal]]></dc:creator>
        <pubDate>2025-05-02T00:00:00.000Z</pubDate>
         
             {
            <category><![CDATA[AI]]></category>
                }
             {
            <category><![CDATA[IntelliJ AI Plugins]]></category>
                }
             {
            <category><![CDATA[Local LLMs]]></category>
                }
             {
            <category><![CDATA[en]]></category>
                }
             
        
		<guid isPermaLink="false">https://blog.lunatech.com//posts/2025-05-02-ai-plugins-for-code-development</guid>

					<description>
                        <![CDATA[ Recently, I experimented with integrating AI into my IntelliJ IDEA setup for JVM development, and I wanted to share the steps I followed. It turned out to be really helpful, so maybe this guide can assist someone else in getting started too!]]></description>
                    <content:encoded><![CDATA[
                    <div class="sect1">
<h2 id="_introduction">Introduction</h2>
<div class="sectionbody">
<div class="paragraph">
<p>Recently, I experimented with integrating AI into my IntelliJ IDEA setup for JVM development, and I wanted to share the steps I followed. It turned out to be really helpful, so maybe this guide can assist someone else in getting started too!</p>
</div>
<div class="paragraph">
<p>IntelliJ is one of the preferred IDE for Java, Scala and Kotlin development. I have been using the IntelliJ IDEA with plugins for AI, which allows me to use Local LLMs to generate code suggestions, refactor my code and even write tests for me.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_what_i_did">What I did</h2>
<div class="sectionbody">
<div class="paragraph">
<p><strong>Step 1: Install Ollama</strong></p>
</div>
<div class="paragraph">
<p>First, visit <a href="https://ollama.com/">Ollama</a> and download the version for your operating system. Follow the simple installation steps.</p>
</div>
<div class="paragraph">
<p>Open your terminal and run <code>ollama pull llama3</code> to download the model. Start the model by running <code>ollama serve llama3</code>.</p>
</div>
<div class="admonitionblock tip">
<table>
<tr>
<td class="icon">
<div class="title">Tip</div>
</td>
<td class="content">
Choosing the right model is very important .
</td>
</tr>
</table>
</div>
<div class="paragraph">
<p><strong>Step 2: IntelliJ Plugins</strong></p>
</div>
<div class="paragraph">
<p>I tested a few plugins and found Continue.dev really useful:</p>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<div class="title">Note</div>
</td>
<td class="content">
A list of plugins at the bottom of this article with links
</td>
</tr>
</table>
</div>
<div class="paragraph">
<p>Continue.dev
Helps with code completion, converting comments into code, and debugging tips.
Works locally (privacy-friendly), quick.
Needs decent hardware resources.</p>
</div>
<div class="paragraph">
<p><strong>Step 3: Setting Up Continue.dev with IntelliJ</strong></p>
</div>
<div class="paragraph">
<p>Install the Plugin:
Open IntelliJ IDEA, navigate to Settings &#8594; Plugins, search for "Continue.dev", and install it.</p>
</div>
<div class="paragraph">
<p>Connect to Ollama:
Open the Continue.dev settings and add the local Ollama server URL (<code><a href="http://localhost:11434" class="bare">http://localhost:11434</a></code>).</p>
</div>
<div class="paragraph">
<p><strong>Step 4: Exploring AI Features</strong></p>
</div>
<div class="paragraph">
<p>Code Suggestions:
The plugin provided accurate code completions immediately, significantly speeding up my workflow.</p>
</div>
<div class="paragraph">
<p>Generating Code from Comments:
I tried writing simple English comments, and Continue.dev translated them into functioning code snippets effortlessly.</p>
</div>
<div class="paragraph">
<p>Debugging:
Even when intentionally making small errors, the plugin quickly suggested effective fixes.</p>
</div>
<div class="paragraph">
<p><strong>Step 5: AI-Assisted Refactoring</strong></p>
</div>
<div class="paragraph">
<p>I highlighted some messy code.
Using the AI suggestions via right-click helped clean up and optimize the code efficiently.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_tips_for_best_results">Tips for Best Results:</h2>
<div class="sectionbody">
<div class="paragraph">
<p>Regularly update plugins and AI models for optimal performance.</p>
</div>
<div class="paragraph">
<p>If hardware resources are limited, experiment with smaller models initially.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_intellij_idea_plugins_supporting_local_llm_integration">IntelliJ IDEA Plugins Supporting Local LLM Integration</h2>
<div class="sectionbody">
<table class="tableblock frame-all grid-all stretch">
<colgroup>
<col style="width: 14.2857%;">
<col style="width: 28.5714%;">
<col style="width: 28.5714%;">
<col style="width: 28.5715%;">
</colgroup>
<thead>
<tr>
<th class="tableblock halign-left valign-top">Plugin</th>
<th class="tableblock halign-left valign-top">Features</th>
<th class="tableblock halign-left valign-top">Pros</th>
<th class="tableblock halign-left valign-top">Cons</th>
</tr>
</thead>
<tbody>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong><a href="https://plugins.jetbrains.com/plugin/22707-continue">Continue.dev</a></strong></p></td>
<td class="tableblock halign-left valign-top"><div class="content"><div class="ulist">
<ul>
<li>
<p>Code completion</p>
</li>
<li>
<p>Natural language to code generation</p>
</li>
<li>
<p>Inline code explanations</p>
</li>
<li>
<p>Supports multiple local LLM providers</p>
</li>
</ul>
</div></div></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">- Open-source
- Highly customizable
- Supports various local LLMs like Ollama, LM Studio, GPT4All</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">- May require manual configuration for optimal performance</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong><a href="https://plugins.jetbrains.com/plugin/24169-devoxxgenie">DevoxxGenie</a></strong></p></td>
<td class="tableblock halign-left valign-top"><div class="content"><div class="ulist">
<ul>
<li>
<p>Code review and explanation</p>
</li>
<li>
<p>Unit test generation</p>
</li>
<li>
<p>Retrieval-Augmented Generation (RAG)</p>
</li>
<li>
<p>Integration with various local LLMs</p>
</li>
</ul>
</div></div></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">- Fully Java-based
- Rich feature set including RAG and Git Diff viewer
- Supports multiple local LLMs</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">- Interface may be overwhelming for beginners</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong><a href="https://plugins.jetbrains.com/plugin/21056-proxy-ai">Proxy AI</a></strong></p></td>
<td class="tableblock halign-left valign-top"><div class="content"><div class="ulist">
<ul>
<li>
<p>Connects IntelliJ IDEA with locally running LLMs</p>
</li>
<li>
<p>Provides AI assistance features</p>
</li>
</ul>
</div></div></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">- Open-source
- Simple setup for local LLM integration</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">- Limited feature set compared to other plugins</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong><a href="https://plugins.jetbrains.com/plugin/24372-codegpt-chat&#8212;&#8203;ai-agents">CodeGPT</a></strong></p></td>
<td class="tableblock halign-left valign-top"><div class="content"><div class="ulist">
<ul>
<li>
<p>AI-powered code suggestions</p>
</li>
<li>
<p>Chat interface within IntelliJ IDEA</p>
</li>
<li>
<p>Supports local LLMs via LM Studio</p>
</li>
</ul>
</div></div></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">- User-friendly interface
- Supports multiple programming languages</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">- May require additional setup for local LLM integration</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong><a href="https://plugins.jetbrains.com/plugin/22282-jetbrains-ai-assistant">JetBrains AI Assistant</a></strong></p></td>
<td class="tableblock halign-left valign-top"><div class="content"><div class="ulist">
<ul>
<li>
<p>AI-driven code suggestions</p>
</li>
<li>
<p>Code explanations and documentation generation</p>
</li>
<li>
<p>Integration with local LLMs</p>
</li>
</ul>
</div></div></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">- Official JetBrains plugin
- Seamless integration with IntelliJ IDEA</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">- May have limited customization compared to open-source alternatives</p></td>
</tr>
</tbody>
</table>
</div>
</div>
<]]></content:encoded>
					
		
		
			</item>
         
	<item>
		<title>Part 2: Backend Setup with NestJS</title>
		<link>https://blog.lunatech.com//posts/2025-04-22-part-2%3A-backend-setup-with-nestjs</link>
		
		<dc:creator><![CDATA[Jake Ortega]]></dc:creator>
        <pubDate>2025-04-22T00:00:00.000Z</pubDate>
         
             {
            <category><![CDATA[angular]]></category>
                }
             {
            <category><![CDATA[nestjs]]></category>
                }
             {
            <category><![CDATA[postgresql]]></category>
                }
             {
            <category><![CDATA[typeorm]]></category>
                }
             {
            <category><![CDATA[jwt]]></category>
                }
             {
            <category><![CDATA[authentication]]></category>
                }
             {
            <category><![CDATA[frontend]]></category>
                }
             {
            <category><![CDATA[typescript]]></category>
                }
             {
            <category><![CDATA[nodejs]]></category>
                }
             {
            <category><![CDATA[en]]></category>
                }
             
        
		<guid isPermaLink="false">https://blog.lunatech.com//posts/2025-04-22-part-2%3A-backend-setup-with-nestjs</guid>

					<description>
                        <![CDATA[ With our project vision and stack laid out in Part 1, it’s time to build the]]></description>
                    <content:encoded><![CDATA[
                    <div id="preamble">
<div class="sectionbody">
<div class="paragraph">
<p>With our project vision and stack laid out in Part 1, it’s time to build the
backend.
In this part, we’ll scaffold a <strong>NestJS</strong> project, connect it to <strong>PostgreSQL</strong>
via <strong>TypeORM</strong>, and implement secure <strong>JWT-based authentication</strong>.</p>
</div>
<div class="paragraph">
<p>By the end of this part, you’ll have:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>A working NestJS app connected to PostgreSQL</p>
</li>
<li>
<p>A <code>User</code> entity with hashed passwords</p>
</li>
<li>
<p>Endpoints for registration and login</p>
</li>
<li>
<p>JWT authentication using guards and strategies</p>
</li>
<li>
<p>CORS enabled to allow Angular frontend communication</p>
</li>
</ul>
</div>
<hr>
</div>
</div>
<div class="sect2">
<h3 id="_project_structure_overview"><strong>Project Structure Overview</strong></h3>
<div class="paragraph">
<p>Once set up, your backend folder will look like this:</p>
</div>
<div class="literalblock">
<div class="content">
<pre>src/
├── app.module.ts
├── main.ts
├── auth/
│   ├── auth.controller.ts
│   ├── auth.module.ts
│   ├── auth.service.ts
│   ├── dto/
│   │   ├── login.dto.ts
│   │   └── register.dto.ts
│   └── jwt/
│       └── jwt.strategy.ts
├── users/
│   ├── user.entity.ts
│   ├── users.controller.ts
│   ├── users.module.ts
│   └── users.service.ts
.env</pre>
</div>
</div>
<hr>
</div>
<div class="sect2">
<h3 id="_goals_for_part_2"><strong>Goals for Part 2</strong></h3>
<div class="olist arabic">
<ol class="arabic">
<li>
<p>Scaffold a NestJS project with PostgreSQL and TypeORM</p>
</li>
<li>
<p>Create a <code>User</code> entity, DTOs with validation, and an Auth module</p>
</li>
<li>
<p>Implement registration and login with password hashing</p>
</li>
<li>
<p>Add JWT authentication with guards and strategy</p>
</li>
<li>
<p>Enable CORS for frontend connectivity</p>
</li>
</ol>
</div>
<hr>
</div>
<div class="sect2">
<h3 id="_step_1_run_postgresql_and_set_environment_variables"><strong>Step 1: Run PostgreSQL and Set Environment Variables</strong></h3>
<div class="paragraph">
<p>You can use either Docker or Podman.
Run <strong>one</strong> of the following commands in your terminal:</p>
</div>
<div class="paragraph">
<p><strong>Docker:</strong></p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-bash" data-lang="bash">docker run --name pg-nest \
  -e POSTGRES_USER=nestuser \
  -e POSTGRES_PASSWORD=nestpass \
  -e POSTGRES_DB=nestdb \
  -p 5432:5432 \
  -d postgres</code></pre>
</div>
</div>
<div class="paragraph">
<p><strong>Podman:</strong></p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-bash" data-lang="bash">podman run --name pg-nest \
  -e POSTGRES_USER=nestuser \
  -e POSTGRES_PASSWORD=nestpass \
  -e POSTGRES_DB=nestdb \
  -p 5432:5432 \
  -d postgres</code></pre>
</div>
</div>
<div class="paragraph">
<p>Once the project is created in Step 2, add a <code>.env</code> file to your root:</p>
</div>
<div class="literalblock">
<div class="content">
<pre>DB_HOST=localhost DB_PORT=5432 DB_USERNAME=nestuser DB_PASSWORD=nestpass
DB_NAME=nestdb JWT_SECRET=dev_secret BCRYPT_SALT_ROUNDS=10</pre>
</div>
</div>
<hr>
</div>
<div class="sect2">
<h3 id="_step_2_scaffold_the_project_and_install_dependencies"><strong>Step 2: Scaffold the Project and Install Dependencies</strong></h3>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-bash" data-lang="bash">nest new backend
cd backend</code></pre>
</div>
</div>
<div class="paragraph">
<p>Install project dependencies:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-bash" data-lang="bash">npm install @nestjs/typeorm typeorm pg @nestjs/jwt passport-jwt @nestjs/passport bcrypt class-validator class-transformer dotenv</code></pre>
</div>
</div>
<div class="paragraph">
<p>At the top of <code>main.ts</code>, import environment variables:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-ts" data-lang="ts">import "dotenv/config";</code></pre>
</div>
</div>
<div class="paragraph">
<p>Enable CORS:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-ts" data-lang="ts">app.enableCors({
  origin: "http://localhost:4200",
  credentials: true,
});</code></pre>
</div>
</div>
<div class="quoteblock">
<blockquote>
<div class="paragraph">
<p>✅ <strong>Tip</strong>: For production, consider using <code>@nestjs/config</code> for cleaner
environment management.</p>
</div>
</blockquote>
</div>
<hr>
</div>
<div class="sect2">
<h3 id="_step_3_configure_typeorm"><strong>Step 3: Configure TypeORM</strong></h3>
<div class="paragraph">
<p>In <code>app.module.ts</code>:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-ts" data-lang="ts">import { Module } from "@nestjs/common";
import { TypeOrmModule } from "@nestjs/typeorm";
import { UsersModule } from "./users/users.module";
import { AuthModule } from "./auth/auth.module";

@Module({
  imports: [
    TypeOrmModule.forRoot({
      type: "postgres",
      host: process.env.DB_HOST,
      port: parseInt(process.env.DB_PORT, 10),
      username: process.env.DB_USERNAME,
      password: process.env.DB_PASSWORD,
      database: process.env.DB_NAME,
      entities: [__dirname + "/**/*.entity{.ts,.js}"],
      synchronize: true, // ⚠️ Don't use this in production — it'll drop/recreate tables
    }),
    UsersModule,
    AuthModule,
  ],
})
export class AppModule {}</code></pre>
</div>
</div>
<hr>
</div>
<div class="sect2">
<h3 id="_step_4_create_the_user_module_and_entity"><strong>Step 4: Create the User Module and Entity</strong></h3>
<div class="paragraph">
<p>Generate boilerplate:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-bash" data-lang="bash">nest g module users
nest g service users
nest g controller users</code></pre>
</div>
</div>
<div class="paragraph">
<p>In <code>users/user.entity.ts</code>:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-ts" data-lang="ts">import { Exclude } from "class-transformer";
import { Column, Entity, PrimaryGeneratedColumn } from "typeorm";

@Entity()
export class User {
  @PrimaryGeneratedColumn()
  id: number;

  @Column({ unique: true })
  email: string;

  @Column()
  name: string;

  @Column()
  @Exclude()
  password: string;

  @Column()
  role: string;
}</code></pre>
</div>
</div>
<hr>
</div>
<div class="sect2">
<h3 id="_step_5_set_up_the_auth_module"><strong>Step 5: Set Up the Auth Module</strong></h3>
<div class="paragraph">
<p>Generate files:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-bash" data-lang="bash">nest g module auth
nest g service auth
nest g controller auth</code></pre>
</div>
</div>
<div class="sect3">
<h4 id="_step_5a_create_dtos_with_validation">Step 5a: Create DTOs with Validation</h4>
<div class="paragraph">
<p>In <code>auth/dto/register.dto.ts</code>:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-ts" data-lang="ts">import { IsEmail, IsNotEmpty, MinLength } from "class-validator";

export class RegisterDto {
  @IsEmail()
  email: string;

  @MinLength(6)
  password: string;

  @IsNotEmpty()
  name: string;

  @IsNotEmpty()
  role: string;
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>These are like your request payload models with annotations.
Think <code>@NotEmpty</code>, <code>@Email</code>, etc.
The validation logic is handled globally (we’ll wire that up in <code>main.ts</code>
using <code>ValidationPipe</code>).</p>
</div>
<div class="paragraph">
<p>In <code>auth/dto/login.dto.ts</code>:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-ts" data-lang="ts">import { IsEmail, MinLength } from "class-validator";

export class LoginDto {
  @IsEmail()
  email: string;

  @MinLength(6)
  password: string;
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>Enable validation globally in <code>main.ts</code>:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-ts" data-lang="ts">import { ValidationPipe } from "@nestjs/common";

app.useGlobalPipes(new ValidationPipe({ whitelist: true }));</code></pre>
</div>
</div>
<hr>
</div>
</div>
<div class="sect2">
<h3 id="_step_6_implement_usersservice"><strong>Step 6: Implement UsersService</strong></h3>
<div class="paragraph">
<p>This service handles persistence logic using TypeORM’s repository pattern.
In <code>users.service.ts</code>:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-ts" data-lang="ts">import { Injectable } from "@nestjs/common";
import { InjectRepository } from "@nestjs/typeorm";
import { Repository } from "typeorm";
import { User } from "./user.entity";

@Injectable()
export class UsersService {
  constructor(
    @InjectRepository(User)
    private repo: Repository&lt;User&gt;
  ) {}

  create(data: Partial&lt;User&gt;) {
    const user = this.repo.create(data);
    return this.repo.save(user);
  }

  findByEmail(email: string) {
    return this.repo.findOne({ where: { email } });
  }
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>Again, if you’re used to JPA, this is just standard repository stuff.</p>
</div>
<div class="paragraph">
<p>In <code>users.module.ts</code>:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-ts" data-lang="ts">import { Module } from "@nestjs/common";
import { TypeOrmModule } from "@nestjs/typeorm";
import { User } from "./user.entity";
import { UsersService } from "./users.service";
import { UsersController } from "./users.controller";

@Module({
  imports: [TypeOrmModule.forFeature([User])],
  providers: [UsersService],
  controllers: [UsersController],
  exports: [UsersService],
})
export class UsersModule {}</code></pre>
</div>
</div>
<hr>
</div>
<div class="sect2">
<h3 id="_step_7_build_authservice"><strong>Step 7: Build AuthService</strong></h3>
<div class="paragraph">
<p>This is where registration and login happens.
We hash passwords with <code>bcrypt</code>, and return a JWT if login succeeds.</p>
</div>
<div class="paragraph">
<p>You’ll notice:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-ts" data-lang="ts">delete user.password;</code></pre>
</div>
</div>
<div class="paragraph">
<p>It manually removes the password before returning the user — feels a bit
hacky, but we’ve also used <code>@Exclude()</code> in the entity, so this is just being
extra cautious.</p>
</div>
<div class="quoteblock">
<blockquote>
<div class="paragraph">
<p>⚠️ We’re using both <code>@Exclude()</code> (to hide the password when transforming
entities) and <code>delete user.password</code> as a backup.
Depending on how Nest returns the object — directly vs. through a
serialization step — the password field might still leak through without
this extra guard.</p>
</div>
</blockquote>
</div>
<div class="paragraph">
<p>In <code>auth.service.ts</code>:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-ts" data-lang="ts">import { Injectable, UnauthorizedException } from "@nestjs/common";
import * as bcrypt from "bcrypt";
import { JwtService } from "@nestjs/jwt";
import { UsersService } from "../users/users.service";
import { RegisterDto } from "./dto/register.dto";
import { LoginDto } from "./dto/login.dto";

@Injectable()
export class AuthService {
  constructor(
    private usersService: UsersService,
    private jwtService: JwtService
  ) {}

  async register(dto: RegisterDto) {
    const existing = await this.usersService.findByEmail(dto.email);
    if (existing) throw new UnauthorizedException("Email already in use");

    const hashed = await bcrypt.hash(dto.password, 10);
    const user = await this.usersService.create({
      ...dto,
      password: hashed,
    });
    delete user.password;
    return user;
  }

  async login(dto: LoginDto) {
    const user = await this.usersService.findByEmail(dto.email);
    const valid = user &amp;&amp; (await bcrypt.compare(dto.password, user.password));
    if (!valid) throw new UnauthorizedException("Invalid credentials");

    const payload = { sub: user.id, role: user.role };
    return { access_token: this.jwtService.sign(payload) };
  }
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>In <code>auth.module.ts</code>:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-ts" data-lang="ts">import { Module } from "@nestjs/common";
import { JwtModule } from "@nestjs/jwt";
import { AuthService } from "./auth.service";
import { AuthController } from "./auth.controller";
import { UsersModule } from "../users/users.module";
import { JwtStrategy } from "./jwt/jwt.strategy";

@Module({
  imports: [
    UsersModule,
    JwtModule.register({
      secret: process.env.JWT_SECRET,
      signOptions: { expiresIn: "1d" },
    }),
  ],
  providers: [AuthService, JwtStrategy],
  controllers: [AuthController],
})
export class AuthModule {}</code></pre>
</div>
</div>
<hr>
</div>
<div class="sect2">
<h3 id="_step_8_jwt_strategy_and_guards"><strong>Step 8: JWT Strategy and Guards</strong></h3>
<div class="paragraph">
<p>Here we set up Passport’s JWT strategy.
If you’re new to Passport: it’s just NestJS’s way of plugging in different
auth strategies.</p>
</div>
<div class="paragraph">
<p>Create the strategy file:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-bash" data-lang="bash">touch src/auth/jwt/jwt.strategy.ts</code></pre>
</div>
</div>
<div class="paragraph">
<p>In <code>jwt.strategy.ts</code>:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-ts" data-lang="ts">import { Injectable } from "@nestjs/common";
import { PassportStrategy } from "@nestjs/passport";
import { ExtractJwt, Strategy } from "passport-jwt";

@Injectable()
export class JwtStrategy extends PassportStrategy(Strategy) {
  constructor() {
    super({
      jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
      secretOrKey: process.env.JWT_SECRET,
    });
  }

  validate(payload: any) {
    return { id: payload.sub, role: payload.role };
  }
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>This function runs once the JWT is verified.
It attaches the returned object to <code>req.user</code>.</p>
</div>
<div class="paragraph">
<p>So if you hit a route with a valid JWT, this is what gets injected.</p>
</div>
<hr>
</div>
<div class="sect2">
<h3 id="_step_9_connect_auth_routes"><strong>Step 9: Connect Auth Routes</strong></h3>
<div class="paragraph">
<p>In <code>auth.controller.ts</code>:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-ts" data-lang="ts">import { Controller, Post, Body } from "@nestjs/common";
import { AuthService } from "./auth.service";
import { RegisterDto } from "./dto/register.dto";
import { LoginDto } from "./dto/login.dto";

@Controller("auth")
export class AuthController {
  constructor(private authService: AuthService) {}

  @Post("register")
  register(@Body() dto: RegisterDto) {
    return this.authService.register(dto);
  }

  @Post("login")
  login(@Body() dto: LoginDto) {
    return this.authService.login(dto);
  }
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>Two routes here:</p>
</div>
<div class="ulist">
<ul>
<li>
<p><code>POST /auth/register</code> → Creates a user</p>
</li>
<li>
<p><code>POST /auth/login</code> → Validates user and returns a token</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>Nice and clean.</p>
</div>
<hr>
</div>
<div class="sect2">
<h3 id="_step_10_test_it"><strong>Step 10: Test It</strong></h3>
<div class="paragraph">
<p>Start your server:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-bash" data-lang="bash">npm run start:dev</code></pre>
</div>
</div>
<div class="paragraph">
<p>Use Postman or Insomnia:</p>
</div>
<div class="sect3">
<h4 id="_register">Register</h4>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-http" data-lang="http">POST /auth/register
Content-Type: application/json

{
  "email": "test@example.com",
  "password": "123456",
  "name": "Test User",
  "role": "user"
}</code></pre>
</div>
</div>
</div>
<div class="sect3">
<h4 id="_login">Login</h4>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-http" data-lang="http">POST /auth/login
Content-Type: application/json

{
  "email": "test@example.com",
  "password": "123456"
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>Response:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-json" data-lang="json">{
  "access_token": "&lt;JWT_TOKEN&gt;"
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>Use this token to access protected routes with:</p>
</div>
<div class="literalblock">
<div class="content">
<pre>Authorization: Bearer &lt;JWT_TOKEN&gt;</pre>
</div>
</div>
<hr>
</div>
</div>
<div class="sect2">
<h3 id="_recap"><strong>Recap</strong></h3>
<div class="paragraph">
<p>You now have:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>A functional NestJS backend with PostgreSQL</p>
</li>
<li>
<p>User registration and login with secure hashed passwords</p>
</li>
<li>
<p>JWT-based authentication strategy and guards</p>
</li>
<li>
<p>DTO validation and global pipes</p>
</li>
<li>
<p>Environment config and CORS enabled for the frontend</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>👉 <strong>Next up (Part 3): We’ll switch gears and start building the Angular
frontend — hooking it up to this backend, wiring in JWT auth, and securing
client-side routes.</strong></p>
</div>
</div>
<]]></content:encoded>
					
		
		
			</item>
         
	<item>
		<title>GenAI: Optimizing Local Large Language Models Performance</title>
		<link>https://blog.lunatech.com//posts/2025-04-17-genai%3A-optimizing-local-large-language-models-performance</link>
		
		<dc:creator><![CDATA[Radek Kargul]]></dc:creator>
        <pubDate>2025-04-17T00:00:00.000Z</pubDate>
         
             {
            <category><![CDATA[gen-ai]]></category>
                }
             {
            <category><![CDATA[llm]]></category>
                }
             {
            <category><![CDATA[generative-ai]]></category>
                }
             {
            <category><![CDATA[local-llm]]></category>
                }
             {
            <category><![CDATA[ollama]]></category>
                }
             {
            <category><![CDATA[quantization]]></category>
                }
             {
            <category><![CDATA[model-optimization]]></category>
                }
             {
            <category><![CDATA[neural-networks]]></category>
                }
             {
            <category><![CDATA[model-inference]]></category>
                }
             {
            <category><![CDATA[open-source]]></category>
                }
             {
            <category><![CDATA[en]]></category>
                }
             
        
		<guid isPermaLink="false">https://blog.lunatech.com//posts/2025-04-17-genai%3A-optimizing-local-large-language-models-performance</guid>

					<description>
                        <![CDATA[ Local large language models (LLMs) are becoming more capable and accessible than ever — but to truly unlock their power, you need to know how to optimize them.]]></description>
                    <content:encoded><![CDATA[
                    <div id="preamble">
<div class="sectionbody">
<div class="paragraph">
<p>Local large language models (LLMs) are becoming more capable and accessible than ever — but to truly unlock their power, you need to know how to optimize them.
Whether you&#8217;re running AI on an M-series MacBook or a 2019 Intel machine, there are tricks to get better speed, quality, and control.</p>
</div>
<div class="paragraph">
<p>In the final session of our GenAI series (after covering Local Dev, RAG, and Agents), we explored the real-world performance tuning of local LLMs.
Here&#8217;s what we covered 👇</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_1_running_llms_on_your_laptop">1. Running LLMs on Your Laptop</h2>
<div class="sectionbody">
<div class="sect2">
<h3 id="_apple_silicon_vs_intel_macs">Apple Silicon vs Intel Macs</h3>
<table class="tableblock frame-all grid-all stretch">
<colgroup>
<col style="width: 42.8571%;">
<col style="width: 28.5714%;">
<col style="width: 28.5715%;">
</colgroup>
<thead>
<tr>
<th class="tableblock halign-left valign-top">Feature</th>
<th class="tableblock halign-left valign-top">Apple Silicon (M1/M2/M3/M4)</th>
<th class="tableblock halign-left valign-top">Intel Mac (e.g. 2019 MBP)</th>
</tr>
</thead>
<tbody>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">CPU &amp; GPU</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Unified on one chip (SoC)</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Separate chips for CPU and GPU</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">Memory</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Shared Unified Memory Architecture</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">RAM for CPU, VRAM for GPU</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">Model performance</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Fast, efficient, great for LLMs</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Slower, GPU mostly unused</p></td>
</tr>
</tbody>
</table>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<div class="title">Note</div>
</td>
<td class="content">
<div class="paragraph">
<p>M-series chips shine for local AI workloads thanks to unified memory.</p>
</div>
<div class="paragraph">
<p>Intel Macs can still work well but rely entirely on CPUs and may struggle with larger models.</p>
</div>
</td>
</tr>
</table>
</div>
</div>
<div class="sect2">
<h3 id="_what_can_you_run">What Can You Run?</h3>
<div class="paragraph">
<p>Models are measured by <strong>parameters</strong>, typically in billions (e.g., 3B, 7B, 13B).
More parameters = more "intelligence" — but also more memory use.</p>
</div>
<div class="paragraph">
<p>Use quantization (more below!) to fit larger models, even on machines with 8–16 GB RAM.</p>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_2_quantization_making_llms_lighter">2. Quantization: Making LLMs Lighter</h2>
<div class="sectionbody">
<div class="sect2">
<h3 id="_what_is_quantization">What is Quantization?</h3>
<div class="paragraph">
<p>Quantization reduces the <strong>precision of the numbers</strong> in a model — trading a little accuracy for huge gains in size and speed.</p>
</div>
<table class="tableblock frame-all grid-all stretch">
<colgroup>
<col style="width: 20%;">
<col style="width: 40%;">
<col style="width: 40%;">
</colgroup>
<thead>
<tr>
<th class="tableblock halign-left valign-top">Format</th>
<th class="tableblock halign-left valign-top">Description</th>
<th class="tableblock halign-left valign-top">Typical Use</th>
</tr>
</thead>
<tbody>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">FP32</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Full precision</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Training</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">FP16</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Half precision</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Deployment</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">INT8</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Quantized</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Light inference (some loss)</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">INT4</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Heavily quantized</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Fast local inference</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">INT2–3</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Experimental</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Ultra-lightweight, niche</p></td>
</tr>
</tbody>
</table>
<div class="exampleblock">
<div class="content">
<div class="paragraph">
<p>LLaMA2-70B goes from <strong>138GB (FP16)</strong> to <strong>42GB (INT4)</strong> — a huge saving!</p>
</div>
</div>
</div>
</div>
<div class="sect2">
<h3 id="_what_is_gguf">What is GGUF?</h3>
<div class="paragraph">
<p><code>GGUF</code> stands for <strong>GPT-Generated Unified Format</strong>.
It’s a modern, standardized file format designed for running <strong>quantized large language models (LLMs) locally</strong>.</p>
</div>
<div class="sect3">
<h4 id="_why_gguf">Why GGUF?</h4>
<div class="paragraph">
<p>GGUF makes loading and using models in tools like <code>llama.cpp</code>, <code>Ollama</code>, or <code>LM Studio</code>.</p>
</div>
<table class="tableblock frame-all grid-all stretch">
<colgroup>
<col style="width: 25%;">
<col style="width: 75%;">
</colgroup>
<thead>
<tr>
<th class="tableblock halign-left valign-top">Feature</th>
<th class="tableblock halign-left valign-top">Benefit</th>
</tr>
</thead>
<tbody>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">🧳 Compact</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Stores quantized models in a smaller, efficient format</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">🧠 Self-contained</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Includes weights, tokenizer, metadata, and vocab in one file</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">⚡ Fast</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Optimized for quick loading and inference</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">🔧 Flexible</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Supports various quantization formats like <code>Q4_K_M</code>, <code>Q5_K_S</code>, etc.</p></td>
</tr>
</tbody>
</table>
</div>
<div class="sect3">
<h4 id="_tools_that_support_gguf">Tools that Support GGUF</h4>
<div class="ulist">
<ul>
<li>
<p><code>llama.cpp</code> – Core backend for CPU/GPU inference</p>
</li>
<li>
<p><code>Ollama</code> – CLI + API for local models</p>
</li>
<li>
<p><code>LM Studio</code> – Desktop GUI for Mac/Windows/Linux</p>
</li>
<li>
<p><code>text-generation-webui</code> – Powerful browser-based frontend</p>
</li>
</ul>
</div>
</div>
<div class="sect3">
<h4 id="_example_gguf_model_filename">Example GGUF Model Filename</h4>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-text" data-lang="text">mistral-7b-instruct-v0.1.Q4_K_M.gguf</code></pre>
</div>
</div>
<table class="tableblock frame-all grid-all stretch">
<colgroup>
<col style="width: 25%;">
<col style="width: 75%;">
</colgroup>
<thead>
<tr>
<th class="tableblock halign-left valign-top">Part</th>
<th class="tableblock halign-left valign-top">Description</th>
</tr>
</thead>
<tbody>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>mistral-7b-instruct</code></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Model type and size</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>v0.1</code></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Model version</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>Q4_K_M</code></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Quantization type (4-bit, medium group)</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>.gguf</code></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">File format extension</p></td>
</tr>
</tbody>
</table>
<div class="quoteblock">
<blockquote>
<div class="paragraph">
<p>Think of a <code>.gguf</code> file as an <strong>AI-in-a-box</strong> — it includes everything the model needs to run locally, compressed and ready to go.</p>
</div>
</blockquote>
</div>
</div>
</div>
<div class="sect2">
<h3 id="_k_quant_types_for_gguf_models">K-Quant Types (for GGUF Models)</h3>
<div class="paragraph">
<p>When downloading quantized models (especially in GGUF format), you&#8217;ll often see suffixes like <code>Q4_K_S</code>, <code>Q5_K_M</code>, or <code>Q6_K_L</code>.
These aren&#8217;t just random labels — they define <strong>how the quantization is applied</strong>, and they directly affect <strong>model quality vs. performance</strong>.</p>
</div>
<div class="paragraph">
<p>The <code>K</code> in these names refers to the <strong>quantization group size and method</strong>, which influences:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>how much precision is preserved;</p>
</li>
<li>
<p>how fast the model can run;</p>
</li>
<li>
<p>how much RAM is required.</p>
</li>
</ul>
</div>
<table class="tableblock frame-all grid-all stretch">
<colgroup>
<col style="width: 25%;">
<col style="width: 75%;">
</colgroup>
<thead>
<tr>
<th class="tableblock halign-left valign-top">Suffix</th>
<th class="tableblock halign-left valign-top">Description</th>
</tr>
</thead>
<tbody>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>K_S</code></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>Small group quantization</strong>
Fastest and most memory-efficient. It compresses more aggressively, which means it&#8217;s ideal when you&#8217;re on a tight memory budget or running on weaker hardware — but output quality might noticeably degrade on complex tasks.</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>K_M</code></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>Medium group quantization</strong>
A great balance of speed, memory use, and output quality. It&#8217;s the "safe middle ground" for most users running 4–7B models locally. If you&#8217;re unsure where to start, this is a solid default.</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>K_L</code></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>Large group quantization</strong>
More conservative compression — keeps more precision, giving higher-quality outputs. Slower and uses more RAM, but closer to non-quantized behavior. Ideal for tasks requiring accurate and nuanced responses.</p></td>
</tr>
</tbody>
</table>
<div class="paragraph">
<p>The difference isn&#8217;t <strong>just</strong> in speed — it&#8217;s also in how much subtle detail the model retains in its responses.</p>
</div>
<div class="quoteblock">
<blockquote>
<div class="paragraph">
<p>“Think of <code>K_S</code>, <code>K_M</code>, and <code>K_L</code> as image compression presets:
<strong>Small</strong> is low-res JPEG, <strong>Medium</strong> is standard HD, <strong>Large</strong> is almost RAW quality.”</p>
</div>
</blockquote>
</div>
</div>
<div class="sect2">
<h3 id="_what_is_quantization_used_for">What is Quantization used for?</h3>
<div class="paragraph">
<p>Quantization is a trade-off between size, speed, and accuracy.
For some perspective, here’s a rough guide on how quantization is used in the LLM world:</p>
</div>
<table class="tableblock frame-all grid-all stretch">
<colgroup>
<col style="width: 33.3333%;">
<col style="width: 66.6667%;">
</colgroup>
<thead>
<tr>
<th class="tableblock halign-left valign-top">Task</th>
<th class="tableblock halign-left valign-top">Quantization</th>
</tr>
</thead>
<tbody>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">Model training</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">FP32 (that&#8217;s why it is so expensive to train models, to get that knowledge accurate)</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">For deployment</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Usually FP16 (for speed)</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">Local models</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Unused INT4 (for speed and accuracy)</p></td>
</tr>
</tbody>
</table>
</div>
<div class="sect2">
<h3 id="_why_not_just_use_a_smaller_model">Why Not Just Use a Smaller Model?</h3>
<div class="ulist">
<ul>
<li>
<p>Models under 3B can run easily — but often lack reasoning or language nuance.</p>
</li>
<li>
<p>Quantization gives you <strong>the best of both worlds</strong>: keep a 7B+ model’s brain but shrink the size.</p>
</li>
</ul>
</div>
<div class="quoteblock">
<blockquote>
<div class="paragraph">
<p>“It’s like watching a 4K movie compressed to 1080p — smaller, still looks good.”</p>
</div>
</blockquote>
</div>
</div>
<div class="sect2">
<h3 id="_quantized_models_in_action_example">Quantized Models In Action (Example)</h3>
<div class="paragraph">
<p>In this example, we consider <a href="https://ollama.com/library/qwen2.5/tags">qwen2.5</a>, a 14B model with quantized versions available in <code>Ollama</code>.
We will focus on different quantization levels of the 14B model.</p>
</div>
<div class="paragraph">
<p>Let&#8217;s have a look at how different models deal with the following prompt:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-text" data-lang="text">Explain recursion to a 10-year-old in one paragraph.</code></pre>
</div>
</div>
<div class="paragraph">
<p>To run the models, execute one of the following prompts, starting with Q4_0:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-shell" data-lang="shell">ollama run qwen2.5:14b-instruct-q4_0
ollama run qwen2.5:14b-instruct-q8_0
ollama run qwen2.5:14b-instruct-q2_K
ollama run qwen2.5:14b-instruct-fp16</code></pre>
</div>
</div>
<div class="paragraph">
<p>For example, let&#8217;s start with Q4_0:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-shell" data-lang="shell">ollama run qwen2.5:14b-instruct-q4_0</code></pre>
</div>
</div>
<div class="paragraph">
<p>Now that the model is loaded, we can run the prompt:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-shell" data-lang="shell">"Explain recursion to a 10-year-old in one paragraph."</code></pre>
</div>
</div>
<div class="paragraph">
<p>Pay attention to the response time and the memory usage.
Compare it with the other models.</p>
</div>
<div class="paragraph">
<p>You may have noticed there is not much difference in quality between the Q4_0 and Q8_0 models, but the Q2_K model is much faster and smaller.
Perfect for showing the quality/speed trade-off in action, and how to adjust for your needs.
This does not necessarily mean that the behavior is the same for other prompts or tasks.
You have to try this for yourself and see what works best for you on your machine.</p>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_3_tuning_parameters_in_ollama">3. Tuning Parameters in Ollama</h2>
<div class="sectionbody">
<div class="paragraph">
<p>Using <strong>Ollama</strong>?
You can change some parameter settings of the local models based on your preference, for example, a more deterministic response, or a more creative one.</p>
</div>
<div class="paragraph">
<p>Let us consider the <code>llama3</code> model, we can run it with the following command:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-shell" data-lang="shell">ollama run llama3</code></pre>
</div>
</div>
<div class="paragraph">
<p>You can set these parameters after the model is loaded:</p>
</div>
<div class="listingblock">
<div class="content">
<pre>/set parameter &lt;parameter&gt; &lt;value&gt;</pre>
</div>
</div>
<div class="paragraph">
<p>So, for example, to set <code>temperature</code> to 1.0:</p>
</div>
<div class="listingblock">
<div class="content">
<pre>/set parameter temperature 1.0</pre>
</div>
</div>
<div class="paragraph">
<p>And then we set <code>top_p</code> to 0.9:</p>
</div>
<div class="listingblock">
<div class="content">
<pre>/set parameter top_p 0.9</pre>
</div>
</div>
<div class="paragraph">
<p>In the example above, we set the <code>temperature</code> to 1.0, a more creative response, and <code>top_p</code> to 0.9, a more deterministic response.
Parameter <code>temperature</code> adds randomness.
The lower the value, the more focused and deterministic the model response.
The higher the value, the more creative and varied the response.
Parameter <code>top_p</code> picks from the smallest possible set of words whose cumulative probability adds up to <code>p</code>.
It controls diversity — higher values mean more diverse and creative responses, and lower values make responses more focused.</p>
</div>
<div class="paragraph">
<p>Here are some more common parameters you can tune:</p>
</div>
<table class="tableblock frame-all grid-all stretch">
<colgroup>
<col style="width: 25%;">
<col style="width: 50%;">
<col style="width: 25%;">
</colgroup>
<thead>
<tr>
<th class="tableblock halign-left valign-top">Param</th>
<th class="tableblock halign-left valign-top">What it Does</th>
<th class="tableblock halign-left valign-top">Typical Values</th>
</tr>
</thead>
<tbody>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">num_ctx</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Context size (how much it remembers)</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">2048–4096</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">top_k</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Limits top options for output</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">40–100</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">top_p</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Controls diversity</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">0.8–0.95</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">temperature</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Controls creativity</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">0.6–0.8 (chat), 0.3–0.6 (code)</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">repeat_penalty</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Avoids repeating phrases</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">1.1–1.3</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">threads</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Number of CPU threads (config only)</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Match to physical cores</p></td>
</tr>
</tbody>
</table>
<div class="paragraph">
<p>If you want to learn more about the parameters, you can find some extra information <a href="https://learnprompting.org/blog/llm-parameters?srsltid=AfmBOoorA2XSH8rxtzvLZcSstK1mp8Hzrj-o5uJRIXKOHVUhAmvcsW5u">here</a>.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_resources">Resources</h2>
<div class="sectionbody">
<div class="ulist">
<ul>
<li>
<p><a href="https://www.tensorops.ai/post/what-are-quantized-llms">What Are Quantized LLMs – TensorOps</a></p>
</li>
<li>
<p><a href="https://www.youtube.com/watch?v=K75j8MkwgJ0">Quantization Explained – YouTube</a></p>
</li>
<li>
<p><a href="https://pieces.app/blog/llm-parameters">LLM Parameters – Pieces Blog</a></p>
</li>
</ul>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_final_thoughts">Final Thoughts</h2>
<div class="sectionbody">
<div class="paragraph">
<p>Running LLMs locally is no longer science fiction — it&#8217;s practical, efficient, and private.
With just a bit of tuning and the right model format, your laptop becomes an AI powerhouse.</p>
</div>
</div>
</div>
<]]></content:encoded>
					
		
		
			</item>
         
	<item>
		<title>Part 1: Introduction and Stack Breakdown for the Angular + NestJS Auth Boilerplate</title>
		<link>https://blog.lunatech.com//posts/2025-04-04-part-1-introduction-&amp;-stack-breakdown-for-the-angular-+-nestjs-auth-boilerplate</link>
		
		<dc:creator><![CDATA[Jake Ortega]]></dc:creator>
        <pubDate>2025-04-04T00:00:00.000Z</pubDate>
         
             {
            <category><![CDATA[angular]]></category>
                }
             {
            <category><![CDATA[nestjs]]></category>
                }
             {
            <category><![CDATA[postgresql]]></category>
                }
             {
            <category><![CDATA[typeorm]]></category>
                }
             {
            <category><![CDATA[jwt]]></category>
                }
             {
            <category><![CDATA[authentication]]></category>
                }
             {
            <category><![CDATA[frontend]]></category>
                }
             {
            <category><![CDATA[typescript]]></category>
                }
             {
            <category><![CDATA[nodejs]]></category>
                }
             {
            <category><![CDATA[en]]></category>
                }
             
        
		<guid isPermaLink="false">https://blog.lunatech.com//posts/2025-04-04-part-1-introduction-&amp;-stack-breakdown-for-the-angular-+-nestjs-auth-boilerplate</guid>

					<description>
                        <![CDATA[ Welcome to the first part in this series on building a full-stack]]></description>
                    <content:encoded><![CDATA[
                    <div id="preamble">
<div class="sectionbody">
<div class="paragraph">
<p>Welcome to the first part in this series on building a full-stack
authentication boilerplate with <strong>Angular</strong>, <strong>NestJS</strong>, and <strong>PostgreSQL</strong>.</p>
</div>
<div class="paragraph">
<p>If you’re a backend developer comfortable with APIs, databases, and business
logic—but frontend frameworks feel like foreign territory—this series is for
you.
We’ll walk through the full stack, showing you how to build real
authentication flows while picking up modern Angular features along the way.</p>
</div>
<div class="paragraph">
<p>By the end, you’ll have a production-ready authentication boilerplate you
can reuse in your own projects—or hand off confidently to frontend
collaborators.</p>
</div>
</div>
</div>
<div class="sect2">
<h3 id="_why_angular_nestjs">Why Angular + NestJS?</h3>
<div class="paragraph">
<p>We’re using <strong>Angular</strong> on the frontend and <strong>NestJS</strong> on the backend.
Both are built in <strong>TypeScript</strong>, so you get a unified development experience
without switching mental models.</p>
</div>
<div class="paragraph">
<p>Here’s why this stack works well together:</p>
</div>
<div class="ulist">
<ul>
<li>
<p><strong>Angular</strong> is opinionated, scalable, and modular—perfect for building real
apps, not just prototypes.
Angular 19 introduces useful features like Signals and new control flow
syntax that cut boilerplate and improve performance.</p>
</li>
<li>
<p><strong>NestJS</strong> is a structured backend framework with decorators, guards, and
strong support for things like JWTs and PostgreSQL—ideal for secure
authentication systems.</p>
</li>
<li>
<p><strong>PostgreSQL</strong> is a reliable, battle-tested relational database with great
tooling and support for user/session management.</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>Together, this stack gives you a clean, testable, and scalable
foundation—without gluing together a bunch of libraries yourself.</p>
</div>
</div>
<div class="sect2">
<h3 id="_what_youll_build">What You’ll Build</h3>
<div class="paragraph">
<p>Over this series, you’ll create a modular, full-stack authentication
boilerplate with:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>A NestJS backend featuring JWT login and registration</p>
</li>
<li>
<p>A styled Angular frontend with auth forms and route guards</p>
</li>
<li>
<p>Token management, global error handling, and frontend state control</p>
</li>
<li>
<p>CI/CD pipelines, testing setup, and a containerized dev environment</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>This isn’t a toy app—it’s a starting point for real projects.</p>
</div>
</div>
<div class="sect2">
<h3 id="_whats_new_in_angular_19">What’s New in Angular 19</h3>
<div class="paragraph">
<p>Angular 19 introduces major improvements that simplify frontend development
and reduce complexity:</p>
</div>
<div class="ulist">
<ul>
<li>
<p><strong>Signals</strong> – A new reactive state primitive.
Think of it like <code>useState</code>, but built into Angular.
Great for managing form state and authentication status.</p>
</li>
<li>
<p><strong>Control Flow Syntax</strong> – <code>@if</code>, <code>@for</code>, and <code>@switch</code> clean up your
templates and reduce the need for verbose structural directives.</p>
</li>
<li>
<p><strong>Defer Blocks</strong> – Lazily load components based on app state, perfect for
gating authenticated vs. public views.</p>
</li>
<li>
<p><strong>Improved Change Detection</strong> – Smarter re-rendering out of the box for
better performance.</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>We’ll use these features where they make sense—especially in the login and
registration flows—so you learn by doing.</p>
</div>
</div>
<div class="sect2">
<h3 id="_who_this_is_for">Who This Is For</h3>
<div class="paragraph">
<p>This series is for backend developers who want to:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>Understand modern Angular concepts without getting lost in frontend jargon</p>
</li>
<li>
<p>Build secure, token-based authentication flows using best practices</p>
</li>
<li>
<p>Deploy real full-stack apps with confidence</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>You don’t need Angular experience.
If you know TypeScript, you’ll feel at home.</p>
</div>
</div>
<div class="sect2">
<h3 id="_tools_youll_need">Tools You’ll Need</h3>
<div class="sect3">
<h4 id="_required">Required</h4>
<div class="ulist">
<ul>
<li>
<p><strong>Node.js</strong> – Backend + Angular CLI</p>
</li>
<li>
<p><strong>NestJS CLI</strong> – Backend scaffolding</p>
</li>
<li>
<p><strong>Angular CLI</strong> – Frontend scaffolding</p>
</li>
<li>
<p><strong>PostgreSQL</strong> – Local dev database</p>
</li>
<li>
<p><strong>Git</strong> – Version control</p>
</li>
</ul>
</div>
</div>
<div class="sect3">
<h4 id="_optional_but_helpful">Optional (but helpful)</h4>
<div class="ulist">
<ul>
<li>
<p><strong>Postman</strong> – For testing APIs</p>
</li>
<li>
<p><strong>pgAdmin</strong> – For inspecting the database</p>
</li>
<li>
<p><strong>VS Code</strong> – With TypeScript extensions</p>
</li>
</ul>
</div>
</div>
</div>
<div class="sect2">
<h3 id="_getting_set_up">Getting Set Up</h3>
<div class="olist arabic">
<ol class="arabic">
<li>
<p><strong>Install Node.js</strong><br>
<a href="https://nodejs.org" class="bare">https://nodejs.org</a></p>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-bash" data-lang="bash">node -v
npm -v</code></pre>
</div>
</div>
</li>
<li>
<p><strong>Install Angular and NestJS CLIs</strong></p>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-bash" data-lang="bash">npm install -g @angular/cli @nestjs/cli</code></pre>
</div>
</div>
</li>
<li>
<p><strong>Install PostgreSQL</strong><br>
<a href="https://www.postgresql.org/download" class="bare">https://www.postgresql.org/download</a></p>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-sql" data-lang="sql">CREATE DATABASE auth_boilerplate;</code></pre>
</div>
</div>
</li>
<li>
<p><strong>Initialize Git Repo</strong></p>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-bash" data-lang="bash">git init</code></pre>
</div>
</div>
</li>
</ol>
</div>
</div>
<div class="sect2">
<h3 id="_coming_up_next_part_2">Coming Up Next (Part 2)</h3>
<div class="paragraph">
<p>In Part 2, we’ll scaffold the NestJS backend, hook it up to PostgreSQL with
TypeORM, and implement JWT-based login and registration logic you can
actually ship.</p>
</div>
</div>
<div class="sect2">
<h3 id="_final_thoughts">Final Thoughts</h3>
<div class="paragraph">
<p>This series is about building something real—not another tutorial app you
toss out after reading.
Whether it’s for a SaaS product, side project, or production tool, having a
solid authentication foundation makes every other feature easier to build.</p>
</div>
</div>
<]]></content:encoded>
					
		
		
			</item>
         
	<item>
		<title>Full-Stack Authentication Boilerplate: Angular + NestJS + PostgreSQL</title>
		<link>https://blog.lunatech.com//posts/2025-04-04-full-stack-authentication-boilerplate:-angular-+-nestjs-+-postgresql</link>
		
		<dc:creator><![CDATA[Jake Ortega]]></dc:creator>
        <pubDate>2025-04-04T00:00:00.000Z</pubDate>
         
             {
            <category><![CDATA[angular]]></category>
                }
             {
            <category><![CDATA[nestjs]]></category>
                }
             {
            <category><![CDATA[postgresql]]></category>
                }
             {
            <category><![CDATA[typeorm]]></category>
                }
             {
            <category><![CDATA[jwt]]></category>
                }
             {
            <category><![CDATA[authentication]]></category>
                }
             {
            <category><![CDATA[frontend]]></category>
                }
             {
            <category><![CDATA[typescript]]></category>
                }
             {
            <category><![CDATA[nodejs]]></category>
                }
             {
            <category><![CDATA[en]]></category>
                }
             
        
		<guid isPermaLink="false">https://blog.lunatech.com//posts/2025-04-04-full-stack-authentication-boilerplate:-angular-+-nestjs-+-postgresql</guid>

					<description>
                        <![CDATA[ For backend developers who want to ship full-stack projects—without wrestling with frontend complexity.]]></description>
                    <content:encoded><![CDATA[
                    <h1 id="_a_practical_series_for_backend_developers_building_secure_full_stack_apps" class="sect0">A practical series for backend developers building secure full-stack apps</h1>
<div class="paragraph">
<p>For backend developers who want to ship full-stack projects—without wrestling with frontend complexity.</p>
</div>
<div class="paragraph">
<p>We’re building a <strong>full-stack authentication boilerplate</strong>—a reusable, modular codebase that gives you login, registration, route protection, token handling, and database integration out of the box. Clone it, customize it, and start building faster.</p>
</div>
<div class="sect2">
<h3 id="_why_this_stack">Why This Stack?</h3>
<div class="paragraph">
<p>We chose <strong>Angular 19</strong> and <strong>NestJS</strong> for a reason:</p>
</div>
<div class="ulist">
<ul>
<li>
<p><strong>TypeScript end-to-end</strong>: Write frontend and backend in the same language with consistent tooling.</p>
</li>
<li>
<p><strong>Angular 19</strong> introduces Signals and control flow syntax (<code>@if</code>, <code>@for</code>), simplifying state and UI logic.</p>
</li>
<li>
<p><strong>NestJS</strong> is structured, modular, and test-friendly—ideal for developers coming from Spring or .NET.</p>
</li>
<li>
<p><strong>PostgreSQL</strong> + <strong>TypeORM</strong> provide a robust relational layer with strong typing and migrations.</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>You <strong>could</strong> build this with React, Express, or MongoDB. But we picked this stack for its structure and scalability—great for teams or solo developers who want a solid foundation, not just flexibility.</p>
</div>
</div>
<div class="sect2">
<h3 id="_whats_in_the_series">What’s in the Series?</h3>
<div class="paragraph">
<p>Here’s the roadmap 👇</p>
</div>
<div class="imageblock">
<div class="content">
<img src="../media/2025-04-04-full-stack-authentication-boilerplate:-angular-+-nestjs-+-postgresql/roadmap.png" alt="Roadmap overview">
</div>
</div>
<div class="paragraph">
<p>Each post builds on the last, walking you through:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>✅ JWT login &amp; registration</p>
</li>
<li>
<p>✅ Angular route guards &amp; auth state</p>
</li>
<li>
<p>✅ NestJS modules, guards, and services</p>
</li>
<li>
<p>✅ PostgreSQL setup with TypeORM</p>
</li>
<li>
<p>✅ CI/CD, E2E tests with Playwright, and Docker deployment</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>You don’t need prior Angular or NestJS experience—just TypeScript and backend fundamentals.</p>
</div>
</div>
<div class="sect2">
<h3 id="_why_this_series_exists">Why This Series Exists</h3>
<div class="paragraph">
<p>You don’t need another to-do app.</p>
</div>
<div class="paragraph">
<p>You need a <strong>working authentication foundation</strong>—something you can reuse, extend, and deploy. That’s what this series delivers, while helping you build real frontend + backend skills along the way.</p>
</div>
<div class="paragraph">
<p>Let’s build something you can actually ship.</p>
</div>
</div>
<]]></content:encoded>
					
		
		
			</item>
         
	<item>
		<title>Mastering Typeclass Derivation with Scala 3</title>
		<link>https://blog.lunatech.com//posts/2025-03-07-typeclass-derivation</link>
		
		<dc:creator><![CDATA[Gustavo De Micheli]]></dc:creator>
        <pubDate>2025-03-07T00:00:00.000Z</pubDate>
         
             {
            <category><![CDATA[scala]]></category>
                }
             {
            <category><![CDATA[typeclass]]></category>
                }
             {
            <category><![CDATA[metaprogramming]]></category>
                }
             {
            <category><![CDATA[we-know-scala]]></category>
                }
             {
            <category><![CDATA[scala-lujah]]></category>
                }
             {
            <category><![CDATA[en]]></category>
                }
             
        
		<guid isPermaLink="false">https://blog.lunatech.com//posts/2025-03-07-typeclass-derivation</guid>

					<description>
                        <![CDATA[ When learning about programming we stumble upon the concept of Polymorphism, and]]></description>
                    <content:encoded><![CDATA[
                    <div class="sect1">
<h2 id="_polymorphism">Polymorphism</h2>
<div class="sectionbody">
<div class="paragraph">
<p>When learning about programming we stumble upon the concept of Polymorphism, and
when learning something new I always wonder, why should we care? Besides getting
a new tool on our tool belt I think it&#8217;s important to understand what are we
getting from this new programming trick.</p>
</div>
<div class="paragraph">
<p>Polymorphism, from the Greek "having multiple forms", allows us to define and
implement a set of different algorithms using the same interface. This has the
benefit of lowering the complexity of our system from our client&#8217;s point of view.
By switching to another implementation, they don&#8217;t need to understand what changed
underneath, they just need to know that the interface is honored by another
implementation. And by lowering this complexity we lower the cognitive-load developers
need to have while using our API, making their code easier to maintain.</p>
</div>
<div class="paragraph">
<p>As far as I&#8217;m aware, there are at least 3 types of polymorphism:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>Ad-Hoc</p>
</li>
<li>
<p>Parametric, and</p>
</li>
<li>
<p>Sub-type</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>If you come from a Object Oriented programming background you&#8217;ll recognize the last
one. Sub-type polymorphism is implemented by defining a parent class that
defines an API, and child classes implementing it. Then using a mechanism like
double-dispatch, a implementation is chosen based on the actual subclass being
instantiated:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-scala" data-lang="scala">trait Shape:
    def area: Double

class Square(width: Double) extends Shape:
    override def area: Double = width * width

class Rectangle(width: Double, height: Double) extends Shape:
    override def area: Double = width * height

class Circle(radius: Double) extends Shape:
    override def area: Double = Math.pow(radius, 2) * Math.PI

val s1: Shape = new Circle(4)
val s2: Shape = new Rectangle(4, 2)

s1.area
s2.area</code></pre>
</div>
</div>
<div class="paragraph">
<p>Another type of polymorphism we can find in both Functional and Object Oriented
programming languages is Parametric polymorphism where we don&#8217;t necessarily
provide different implementations based on different types, but rather abstract
over some types:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-scala" data-lang="scala">def identity[A](a: A): A = a

enum List[+A]:
    case Cons(head: A, tail: List[A]) extends List[A]
    case Nil extends List[Nothing]

    def map[B](fn: A =&gt; B): List[B] = this match
        case Cons(head, tail) =&gt; Cons(fn(head), tail.map(fn))
        case Nil =&gt; Nil</code></pre>
</div>
</div>
<div class="paragraph">
<p>The <code>List</code> doesn&#8217;t care what&#8217;s containing, but its <code>map</code> method can easily work
for `Int`s, `String`s, and so on.</p>
</div>
<div class="paragraph">
<p>The last type of polymorphism we mentioned was <em>Ad-Hoc</em> polymorphism, which can
be defined as a "A system where functions or expressions are defined for specific
types". Let&#8217;s see how this gets implemented using Typeclasses.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_typeclasses">Typeclasses</h2>
<div class="sectionbody">
<div class="paragraph">
<p>Typeclasses are a way to implement Ad-Hoc polymorphism with 2 significant properties:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>Separate Definitions: For each relevant class, we define a separate instance of
a function or method (like <code>Show</code>, <code>Eq</code>, etc.) This similar to defining a
separate function for specific types.</p>
</li>
<li>
<p>Context-Dependent Selection: An implementation will be selected based on where
the typeclass is used.</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>In Scala, a Typeclass is implemented by defining 3 parts:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>Interface: What functionality is the Typeclass offering.</p>
</li>
<li>
<p>Instances: How is that functionality implemented.</p>
</li>
<li>
<p>Usage: Where and how is that functionality used.</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>Let&#8217;s see a simple implementation of the <code>Show</code> Typeclass:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-scala" data-lang="scala">// Interface
trait Show[A]:
    def show(a: A): String

// Instances
object Show:
    given Show[Int]     = (i: Int) =&gt; i.toString
    given Show[String]  = (s: String) =&gt; "'" + s + "'"
    given Show[Boolean] = (b: Boolean) =&gt; i.toString

// Usage
def log[A](a: A)(using s: Show[A]): Unit =
    println(s.show(a))</code></pre>
</div>
</div>
<div class="paragraph">
<p>An important detail of the Typeclass definition is that we use a Type Parameter
on it&#8217;s interface, instances, and usage.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_typeclass_derivation">Typeclass Derivation</h2>
<div class="sectionbody">
<div class="paragraph">
<p>An interesting feature of Scala is that we can automatically generate the
instances of a Typeclass by implementing Typeclass Derivation code. This will
make the compiler generate instances at compile-time, making our Typeclass more
usable as we&#8217;ll shift the burden of implementation to our code instead of our
client&#8217;s code.</p>
</div>
<div class="paragraph">
<p>To derive instances for a Typeclass we need:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>Tools to decompose complex types, such as case classes.</p>
</li>
<li>
<p>Tools to compose complex types from more simpler types.</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>And one way we can approach implementing Derivation code is:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>Think Recursively (Base vs. Iterative Case)</p>
</li>
<li>
<p>Implementing one Typeclass by implementing a simpler version first.</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>On Scala 2 we&#8217;d use a library like <a href="https://github.com/milessabin/shapeless">Shapeless</a> or
<a href="https://github.com/softwaremill/magnolia">Magnolia</a> to compose and decompose complex
types. In Scala 3 these features are backed in the language.</p>
</div>
<div class="paragraph">
<p><a href="https://docs.scala-lang.org/scala3/reference/contextual/derivation.html#mirror-1">Mirrors</a> provide
typelevel information about types being derived, with similar features as <em>HList</em> and
<em>Coproduct</em> in a single abstraction.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-scala" data-lang="scala">import scala.collection.AbstractIterable
import scala.compiletime.{erasedValue, error, summonInline}
import scala.deriving.*

// Interface
trait Show[A]:
    def show(a: A): String

// Instances
object Show:
    given Show[Int]     = (i: Int) =&gt; i.toString
    given Show[String]  = (s: String) =&gt; "'" + s + "'"
    given Show[Boolean] = (b: Boolean) =&gt; i.toString

    def iterable[T](p: T): Iterable[Any] = new AbstractIterable[Any]:
        def iterator: Iterator[Any] = p.asInstanceOf[Product].productIterator

    def showProduct[T](p: Mirror.ProductOf[T], elems: =&gt; List[Show[?]]): Show[T] =
        new Show[T]:
            def show(a: A): String =
                iterable(x).lazyZip(elems).map { case (i, s) =&gt; s.show(i) }.mkString(",")

    inline def derived[A](using m: Mirror.ProductOf[A]): Show[A] =
        lazy val elemInstances = summonInstances[T, m.MirroredElemTypes]
        showProduct(m, elemInstances)

    inline def summonInstances[T, Elems &lt;: Tuple]: List[Show[?]] =
        inline erasedValue[Elems] match
            case _: (elem *: elems) =&gt; deriveOrSummon[T, elem] :: summonInstances[T, elems]
            case _: EmptyTuple =&gt; Nil

    inline def deriveOrSummon[T, Elem]: Show[Elem] =
        inline erasedValue[Elem] match
            case _: T =&gt; deriveRec[T, Elem]
            case _    =&gt; summonInline[Show[Elem]]

    inline def deriveRec[T, Elem]: Show[Elem] =
        inline erasedValue[T] match
            case _: Elem =&gt; error("infinite recursive derivation")
            case _       =&gt; Show.derived[Elem](using summonInline[Mirror.Of[Elem]]) // recursive derivation</code></pre>
</div>
</div>
<div class="paragraph">
<p>This is a simplified example of a Typeclass Derivation for the <code>Show</code> Typeclass.
For a more thorough example with a more detailed explanation, I cannot recommend
<a href="https://docs.scala-lang.org/scala3/reference/contextual/derivation.html">Type Class Derivation</a> enough.</p>
</div>
</div>
</div>
<]]></content:encoded>
					
		
		
			</item>
         
	<item>
		<title>The Scala effect: Java’s Evolution Inspired by Scala</title>
		<link>https://blog.lunatech.com//posts/2025-02-28-the-scala-effect</link>
		
		<dc:creator><![CDATA[]]></dc:creator>
        <pubDate>2025-03-04T00:00:00.000Z</pubDate>
         
             {
            <category><![CDATA[jvm]]></category>
                }
             {
            <category><![CDATA[scala]]></category>
                }
             {
            <category><![CDATA[java]]></category>
                }
             {
            <category><![CDATA[java8]]></category>
                }
             {
            <category><![CDATA[java11]]></category>
                }
             {
            <category><![CDATA[java17]]></category>
                }
             {
            <category><![CDATA[java21]]></category>
                }
             {
            <category><![CDATA[we-know-scala]]></category>
                }
             {
            <category><![CDATA[scala-lujah]]></category>
                }
             {
            <category><![CDATA[en]]></category>
                }
             
        
		<guid isPermaLink="false">https://blog.lunatech.com//posts/2025-02-28-the-scala-effect</guid>

					<description>
                        <![CDATA[ Since its inception, Java has been one of the most widely used programming languages,]]></description>
                    <content:encoded><![CDATA[
                    <div class="sect1">
<h2 id="_contents">Contents</h2>
<div class="sectionbody">
<div class="paragraph">
<p>Since its inception, Java has been one of the most widely used programming languages,
known for its stability and enterprise adoption.
However, as modern software development demands more expressive and concise code,
Java has often looked to other languages for inspiration.
One of its biggest influences has been Scala—a language that brought functional programming,
immutability, and expressive syntax to the JVM.</p>
</div>
<div class="paragraph">
<p>Over the years, Java has steadily incorporated many features that were first introduced in Scala,
from lambda expressions and pattern matching to records and data-oriented programming.
In this article, we’ll explore how Java has evolved by adopting concepts from Scala,
breaking down the changes version by version. We&#8217;ll also see some examples,
to see each language&#8217;s unique approach, while pointing out some key differences.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_java_8">Java 8</h2>
<div class="sectionbody">
<div class="sect2">
<h3 id="_stream_api">Stream API</h3>
<div class="paragraph">
<p>I don&#8217;t think I need to introduce many of the readers to the Stream API, born in Java 8.
It is also well known, how it basically changed the game on how you approach operations on collections.
What might be a bit less known is the fact, that this feature is a big step towards functional programming,
since the API promotes functional paradigms, such as immutability, pure functions, higher level functions.
Exploring those paradigms could use a talk in itself, so the below example is rather to show,
from a developer experience perspective how easy it is to do multiple, small operations on a collection,
with the new API compered to the old way.</p>
</div>
<div class="openblock scrollable">
<div class="content">
<table class="tableblock frame-all grid-all stretch">
<colgroup>
<col style="width: 33.3333%;">
<col style="width: 33.3333%;">
<col style="width: 33.3334%;">
</colgroup>
<thead>
<tr>
<th class="tableblock halign-left valign-top">Scala</th>
<th class="tableblock halign-left valign-top">Java (old)</th>
<th class="tableblock halign-left valign-top">Java (new)</th>
</tr>
</thead>
<tbody>
<tr>
<td class="tableblock halign-left valign-top"><div class="content"><div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-scala" data-lang="scala">def getNamesOfMammals(animals: List[Animal]): List[String] =
  animals
    .filter(_.classification == "mammal")
    .map(_.name)</code></pre>
</div>
</div></div></td>
<td class="tableblock halign-left valign-top"><div class="content"><div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">private List&lt;String&gt; getNamesOfMammals(List&lt;Animal&gt; animals) {
    List&lt;String&gt; names = new ArrayList&lt;&gt;();

    for (Animal animal: animals) {
        if (animal.classification.equals("mammal")) {
            names.add(animal.name);
        }
    }

    return names;
}</code></pre>
</div>
</div></div></td>
<td class="tableblock halign-left valign-top"><div class="content"><div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">private List&lt;String&gt; getNamesOfMammals(List&lt;Animal&gt; animals) {
    return animals
        .stream()
        .filter(animal -&gt; animal.classification.equals("mammal"))
        .map(animal -&gt; animal.name)
        .toList();
}</code></pre>
</div>
</div></div></td>
</tr>
</tbody>
</table>
</div>
</div>
<div class="paragraph">
<p>It is worth to note, that the above example is nice, and already a huge step in the right direction,
when it comes to streaming data processing, java still lacks support for a lot of major operations (fold, sliding windows).</p>
</div>
</div>
<div class="sect2">
<h3 id="_optional">Optional</h3>
<div class="paragraph">
<p>Safety first! Especially when it comes to nulls, and java. <code>Option</code> is a core part of the Scala language,
making nullable data a breeze to work with, through great support for operations, and branchless behaviour definition.
Java intends to implement some of that functionality with the <code>Optional</code> class. Just like in the streams' case,
scala still offers more flexibility and more defined developer options, when it comes to potentially missing data (e.g.: <code>exists</code>, <code>forall</code>).
The example illustrates the boilerplate needed to handle nested nullable structures,
and the positive steps java already took in the right direction.</p>
</div>
<div class="openblock scrollable">
<div class="content">
<table class="tableblock frame-all grid-all stretch">
<colgroup>
<col style="width: 33.3333%;">
<col style="width: 33.3333%;">
<col style="width: 33.3334%;">
</colgroup>
<thead>
<tr>
<th class="tableblock halign-left valign-top">Scala</th>
<th class="tableblock halign-left valign-top">Java (old)</th>
<th class="tableblock halign-left valign-top">Java (new)</th>
</tr>
</thead>
<tbody>
<tr>
<td class="tableblock halign-left valign-top"><div class="content"><div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-scala" data-lang="scala">case class Wing(length: Int, fact: Option[String])
case class Animal(name: String, wing: Option[Wing])

def printSafeInterestingWingFacts(animals: List[Animal]) =
  animals.foreach { animal =&gt; println(s"""${animal.name}: ${
    animal.wing
      .flatMap(_.fact)
      .getOrElse("no interesting wing fact :(")}""")}</code></pre>
</div>
</div></div></td>
<td class="tableblock halign-left valign-top"><div class="content"><div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">class Wing{public Integer length; public String fact;}
class Animal{public String name; public Wing wing;}

private void printInterestingWingFacts(List&lt;Animal&gt; animals) {
    for (Animal animal: animals) {
        if (animal.wing != null) {
            if (animal.wing.fact != null) {
                System.out.printf("%s: %s%n", animal.name, animal.wing.fact);
            } else {
                System.out.printf("%s: no interesting wing fact :(%n", animal.name);
            }
        } else {
            System.out.printf("%s: no interesting wing fact :(%n", animal.name);
        }
    }
}</code></pre>
</div>
</div></div></td>
<td class="tableblock halign-left valign-top"><div class="content"><div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">class Wing{public Integer length; public Optional&lt;String&gt; fact;}
class Animal{public String name; public Optional&lt;Wing&gt; wing;}

private void printSafeInterestingWingFacts(List&lt;Animal&gt; animals) {
    animals.forEach(animal -&gt; {
        System.out.printf("%s: %s%n", animal.name, animal.wing
            .flatMap(wing -&gt; wing.fact)
            .orElse("no interesting wing fact :(%n"));
    });
}</code></pre>
</div>
</div></div></td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
<div class="sect2">
<h3 id="_functional_interfaces_lambdas">Functional interfaces (lambdas)</h3>
<div class="paragraph">
<p>One of the key prerequisites of having support for all these functional paradigms, is to be able to pass functions as arguments.
Java implements this concept via so-called functional interfaces. A functional interface, is an interface,
with only one method declared. Java 8 also makes it easier to use these interfaces with the lambda syntax.
With the lambda syntax you can pass lambda functions as arguments, and the compiler will be able to interpret it,
as the needed interface.</p>
</div>
<div class="openblock scrollable">
<div class="content">
<table class="tableblock frame-all grid-all stretch">
<colgroup>
<col style="width: 33.3333%;">
<col style="width: 33.3333%;">
<col style="width: 33.3334%;">
</colgroup>
<thead>
<tr>
<th class="tableblock halign-left valign-top">Scala</th>
<th class="tableblock halign-left valign-top">Java (old)</th>
<th class="tableblock halign-left valign-top">Java (new)</th>
</tr>
</thead>
<tbody>
<tr>
<td class="tableblock halign-left valign-top"><div class="content"><div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-scala" data-lang="scala">def chainEvenNumbers(numbers: List[Int]): String =
  numbers
  .filter(n =&gt; n % 2 == 0)
  .map(n =&gt; n.toString)
  .reduce{case (n1, n2) =&gt; n1 + n2}</code></pre>
</div>
</div></div></td>
<td class="tableblock halign-left valign-top"><div class="content"><div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">String chainEvenNumbers(List&lt;Integer&gt; numbers) {
    Predicate&lt;Integer&gt; predicate = new Predicate&lt;&gt;() {
        @Override
        public boolean test(Integer integer) {
            return integer % 2 == 0;
        }
    };

    Function&lt;Integer, String&gt; mapper = new Function&lt;&gt;() {
        @Override
        public String apply(Integer integer) {
            return integer.toString();
        }
    };

    BinaryOperator&lt;String&gt; accumulator = new BinaryOperator&lt;&gt;() {
        @Override
        public String apply(String s, String s2) {
            return s + s2;
        }
    };

    return numbers
        .stream()
        .filter(predicate)
        .map(mapper)
        .reduce("", accumulator);
}</code></pre>
</div>
</div></div></td>
<td class="tableblock halign-left valign-top"><div class="content"><div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">String chainEvenNumbers(List&lt;Integer&gt; numbers) {
    return numbers
        .stream()
        .filter(i -&gt; i % 2 == 0)
        .map(Object::toString)
        .reduce("", (s, s2) -&gt; s + s2);
}</code></pre>
</div>
</div></div></td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_java_11">Java 11</h2>
<div class="sectionbody">
<div class="paragraph">
<p>Java 11&#8217;s main features fall outside of this article&#8217;s scope, since they are not directly influenced by Scala,
nor resemble existing Scala features. I would like to mention however a couple small additions,
mainly in the area of scripting, and writing / running fast, without overhead.
OVer the years a good argument for learning Scala (or against learning java, really) was that for a beginner,
the learning curve might be steep, and writing small code snippets is not really possible.
On top of that, while it scales up excellent, it is not really ideal for small projects.
The following additions you can argue how much they were inspired by Scala actually (I wouldn&#8217;t argue against it either),
but one thing is not arguable: Scala was always ahead in these topics, and with 11, Java is now one step closer.</p>
</div>
<div class="sect2">
<h3 id="_collectionof_factory_method_java_9"><code><em>&lt;Collection&gt;</em>::of</code> factory method (Java 9)</h3>
<div class="paragraph">
<p>No more dubious initialization, and element adding after, with Java 11 now most of the commonly used collections receive
the <code>::of</code> factory method, where you can quickly create a new immutable instance, with a number of initial elements.</p>
</div>
<div class="openblock scrollable">
<div class="content">
<table class="tableblock frame-all grid-all stretch">
<colgroup>
<col style="width: 33.3333%;">
<col style="width: 33.3333%;">
<col style="width: 33.3334%;">
</colgroup>
<thead>
<tr>
<th class="tableblock halign-left valign-top">Scala</th>
<th class="tableblock halign-left valign-top">Java (old)</th>
<th class="tableblock halign-left valign-top">Java (new)</th>
</tr>
</thead>
<tbody>
<tr>
<td class="tableblock halign-left valign-top"><div class="content"><div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-scala" data-lang="scala">val l: List[Int] = List(1, 2, 3, 4, 5)</code></pre>
</div>
</div></div></td>
<td class="tableblock halign-left valign-top"><div class="content"><div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">List&lt;Integer&gt; l = new ArrayList&lt;&gt;();

l.add(1);
l.add(2);
l.add(3);
l.add(4);
l.add(5);</code></pre>
</div>
</div></div></td>
<td class="tableblock halign-left valign-top"><div class="content"><div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">List&lt;Integer&gt; l = List.of(1, 2, 3, 4, 5);</code></pre>
</div>
</div></div></td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
<div class="sect2">
<h3 id="_introduction_of_jshell_java_repl_java_9">Introduction of <code><em>jshell</em></code> (java REPL) (Java 9)</h3>
<div class="paragraph">
<p>Huge step towards scripting, but also really important for bigger projects. The presence of the jshell
is equally amazing for absolute beginners, as well as seasoned developers. It could be used in various ways,
from writing quick <em>"hello world"</em> code to quickly test out more serious code in a bigger production environment.
The java REPL is not yet that advanced as the Scala counterpart, but this long overdue feature
is again making the language a bit more consumable.</p>
</div>
</div>
<div class="sect2">
<h3 id="_addition_of_var_keyword_java_11">Addition of var keyword (Java 11)</h3>
<div class="paragraph">
<p>If it was not a 100% clear what does it mean, when we talk about steep learning curve for beginners,
or challenges to test out code segment quickly in a bigger environment,
having to quickly write a code like this (in both cases) hopefully explains it:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">void testStateAndTranslator() {
    InternalFrameInternalFrameTitlePaneInternalFrameTitlePaneMaximizeButtonWindowNotFocusedState state = nimbus.getState();
    assert state == expectedState;
    RefreshAuthorizationPolicyProtocolServerSideTranslatorPB translator = hadoop.getTranslator();
    assert translator == expectedTranslator;
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>Now this is a test, where you would most likely get some autocorrection, but imagine the nightmare typing these in the REPL!
Luckily if you want to quicly test out something like this, sice java 11 it would only look like something like this:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">jshell&gt; var state = nimbus.getState()
state ==&gt; InternalFrameInternalFrameTitlePaneInternalFrameT ... owNotFocusedState@1a86f2f1

jshell&gt; state.testStuff()
Stuff works!</code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="_launch_single_file_java_11">Launch single file (Java 11)</h3>
<div class="paragraph">
<p>This is all great so far, but what if you want to write some code quickly to generate input, or want to process a file?
You wouldn&#8217;t want to include that file in your project, and definitely don&#8217;t want to recompile every time you tweak that
<code>println</code> statement. With Java 11, you get another benefit which points java in the scripting direction.
You can run single java files, without associating it to a project, or even without precompiling it.
In fact you can include a <code>she-bang</code> line, and run it as a shell script!</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">❯ javac HelloWorldJava8.java
❯ java HelloWorldJava8
Hello World!
❯ java HelloWorldJava11.java
Hello World!
❯ ./HelloWorldJava11Shell.java
Hello World!</code></pre>
</div>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_java_17">Java 17</h2>
<div class="sectionbody">
<div class="sect2">
<h3 id="_switch_expressions_java_14">Switch expressions (Java 14)</h3>
<div class="paragraph">
<p>Switch expressions' functionality is still limited to the same restrictions as before
(we are going to talk about these restrictions later), but it got a nice facelift,
where you can leave a lot of boilerplate code behind!</p>
</div>
<div class="openblock scrollable">
<div class="content">
<table class="tableblock frame-all grid-all stretch">
<colgroup>
<col style="width: 33.3333%;">
<col style="width: 33.3333%;">
<col style="width: 33.3334%;">
</colgroup>
<thead>
<tr>
<th class="tableblock halign-left valign-top">Scala</th>
<th class="tableblock halign-left valign-top">Java (old)</th>
<th class="tableblock halign-left valign-top">Java (new)</th>
</tr>
</thead>
<tbody>
<tr>
<td class="tableblock halign-left valign-top"><div class="content"><div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-scala" data-lang="scala">def kindergartenToString(number: Int): String =
  number match {
  case 1 =&gt; "1"
  case 2 =&gt; "2"
  case _ =&gt; "cannot count until that"
}</code></pre>
</div>
</div></div></td>
<td class="tableblock halign-left valign-top"><div class="content"><div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">private String kindergartenToString(Integer number) {
    String result;
    switch (number) {
        case 1:
            result = "1";
            break;
        case 2:
            result = "2";
            break;
        default:
            result = "cannot count until that";
    };

    return result;
}</code></pre>
</div>
</div></div></td>
<td class="tableblock halign-left valign-top"><div class="content"><div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">private String kindergartenToString(Integer number) {
    return switch (number) {
        case 1 -&gt; "1";
        case 2 -&gt; "2";
        default -&gt; "cannot count until that";
    };
}</code></pre>
</div>
</div></div></td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
<div class="sect2">
<h3 id="_text_blocks_java_15">Text blocks (Java 15)</h3>
<div class="paragraph">
<p>Another long overdue feature, where you wonder, why exactly did we need to wait until Java 15 for that?</p>
</div>
<div class="openblock scrollable">
<div class="content">
<table class="tableblock frame-all grid-all stretch">
<colgroup>
<col style="width: 33.3333%;">
<col style="width: 33.3333%;">
<col style="width: 33.3334%;">
</colgroup>
<thead>
<tr>
<th class="tableblock halign-left valign-top">Scala</th>
<th class="tableblock halign-left valign-top">Java (old)</th>
<th class="tableblock halign-left valign-top">Java (new)</th>
</tr>
</thead>
<tbody>
<tr>
<td class="tableblock halign-left valign-top"><div class="content"><div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-scala" data-lang="scala">var sql =
  """
    |SELECT
    |  name,
    |  salary,
    |  title
    |FROM
    |  employees
    |WHERE
    |  age &lt; 25
    |  AND title in (
    |    SELECT
    |      summary
    |    FROM
    |      jobs
    |  )
    |""".stripMarging</code></pre>
</div>
</div></div></td>
<td class="tableblock halign-left valign-top"><div class="content"><div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">String sql = "SELECT\n" +
            "  name,\n" +
            "  salary,\n" +
            "  title\n" +
            "FROM\n" +
            "  employees\n" +
            "WHERE\n" +
            "  age &lt; 25\n" +
            "  AND title in (\n" +
            "    SELECT\n" +
            "      summary\n" +
            "    FROM\n" +
            "      jobs\n" +
            "  )";</code></pre>
</div>
</div></div></td>
<td class="tableblock halign-left valign-top"><div class="content"><div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">String sql = """
            SELECT
              name,
              salary,
              title
            FROM
              employees
            WHERE
              age &lt; 25
              AND title in (
                SELECT
                  summary
                FROM
                  jobs
              )""";</code></pre>
</div>
</div></div></td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
<div class="sect2">
<h3 id="_pattern_matching_instanceof_java_16">Pattern matching instanceof (Java 16)</h3>
<div class="paragraph">
<p>You can argue if this in itself is a huge step or not, but this definitely set the table, for what&#8217;s to come with Java 21.
And not having to cast (although it is 100% safe, already from context) by hand every time,
and having to have either multiple casts, or nested branches is already a big step, but let the code speak for itself.</p>
</div>
<div class="openblock scrollable">
<div class="content">
<table class="tableblock frame-all grid-all stretch">
<colgroup>
<col style="width: 33.3333%;">
<col style="width: 33.3333%;">
<col style="width: 33.3334%;">
</colgroup>
<thead>
<tr>
<th class="tableblock halign-left valign-top">Scala</th>
<th class="tableblock halign-left valign-top">Java (old)</th>
<th class="tableblock halign-left valign-top">Java (new)</th>
</tr>
</thead>
<tbody>
<tr>
<td class="tableblock halign-left valign-top"><div class="content"><div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-scala" data-lang="scala">def callIfPositiveInt(any: Any): Unit =
  any match {
    case i: Int =&gt; i.someMethodOnInt()
  }</code></pre>
</div>
</div></div></td>
<td class="tableblock halign-left valign-top"><div class="content"><div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">void callIfPositiveIntImpl1(Object object) {
    if (object instanceof Integer) {
        Integer i = (Integer) object;

        if (i &gt; 0) {
            i.someMethodOnInteger();
        }
    }
}

void callIfPositiveIntImpl2(Object object) {
    if (object instanceof Integer &amp;&amp; ((Integer) object) &gt; 0) {
        Integer i = (Integer) object;
        i.someMethodOnInteger();
    }
}</code></pre>
</div>
</div></div></td>
<td class="tableblock halign-left valign-top"><div class="content"><div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">void callIfPositiveInt(Object object) {
    if (object instanceof Integer i &amp;&amp; i &gt; 0) {
        i.someMethodOnInteger();
    }
}</code></pre>
</div>
</div></div></td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
<div class="sect2">
<h3 id="_record_classes_java_16">Record classes (Java 16)</h3>
<div class="paragraph">
<p>Record classes are a new type declaration, that allows you to compactly define immutable data classes.
They are intended to be transparent carriers of their shallowly immutable data.</p>
</div>
<div class="paragraph">
<p>They resemble the well known <code>case class</code> in Scala. There&#8217;s no such thing as "same" between two languages,
so it goes without saying that they have (on top of the many similarities) some differences.
Exactly discovering all the similarities and differences is outside of the scope of this article,
but from a developer experience perspective, being able to write compact code that speaks for itself
is the same for both.</p>
</div>
<div class="paragraph">
<p>Records are going to be even more powerful in Java 21, paired with pattern matching concepts.</p>
</div>
<div class="openblock scrollable">
<div class="content">
<table class="tableblock frame-all grid-all stretch">
<colgroup>
<col style="width: 33.3333%;">
<col style="width: 33.3333%;">
<col style="width: 33.3334%;">
</colgroup>
<thead>
<tr>
<th class="tableblock halign-left valign-top">Scala</th>
<th class="tableblock halign-left valign-top">Java (old)</th>
<th class="tableblock halign-left valign-top">Java (new)</th>
</tr>
</thead>
<tbody>
<tr>
<td class="tableblock halign-left valign-top"><div class="content"><div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-scala" data-lang="scala">case class Point(x: Int, y: Int)


val point = Point(1, 2)
val x = point.x
val y = point.y
val hashCode = point.hashCode
val s = point.toString // "Point[x=1, y=2]"

assert(point == Point(1, 2))
assert(!(point == Point(2, 2)))</code></pre>
</div>
</div></div></td>
<td class="tableblock halign-left valign-top"><div class="content"><div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">class Point {
    private final Integer x;
    private final Integer y;

    public Point(Integer x, Integer y) {
        this.x = x;
        this.y = y;
    }

    public Integer x() {
        return x;
    }

    public Integer y() {
        return y;
    }

    @Override
    public String toString() {
        return String.format("Point[x=%d, y=%d]", x, y);
    }

    @Override
    public boolean equals(Object object) {
        if (this == object) return true;
        if (!(object instanceof Point point)) return false;
        return Objects.equals(x, point.x) &amp;&amp; Objects.equals(y, point.y);
    }

    @Override
    public int hashCode() {
        return Objects.hash(x, y);
    }
}


Point point = new Point(1, 2);
Integer x = point.x();
Integer y = point.y();
int hashCode = point.hashCode();
String s = point.toString(); // "Point[x=1, y=2]"
assert point.equals(new Point(1, 2));
assert !point.equals(new Point(2, 2));</code></pre>
</div>
</div></div></td>
<td class="tableblock halign-left valign-top"><div class="content"><div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">record Point(Integer x, Integer y) {}


Point point = new Point(1, 2);
Integer x = point.x();
Integer y = point.y();
int hashCode = point.hashCode();
String s = point.toString(); // "Point[x=1, y=2]"
assert point.equals(new Point(1, 2));
assert !point.equals(new Point(2, 2));</code></pre>
</div>
</div></div></td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
<div class="sect2">
<h3 id="_sealed_interfacesclasses_java_17">Sealed interfaces/classes (Java 17)</h3>
<div class="paragraph">
<p>With Scala&#8217;s language focus not just leverages, but was built on <em>pattern matching</em>,
having an option to control your class hierarchy is essential. Hence sealed traits (interfaces)
are essential part of scala. With it you can have fine grained control of the class hierarchy,
and have guarantees for all possible subclasses, making pattern matching even more powerful.
With the power of such features catching java&#8217;s attention, it had to adapt some of the concepts as well.</p>
</div>
<div class="paragraph">
<p>With sealed interfaces it is possible to have exact control over your class subclasses that can implement your class / interface.
With having switch expression coming only in java 21, with java 17 most of the gains is
having all the control over your class hierarchy, enabling you to enforce design principles,
and prevent unauthorized extensions.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">sealed interface Animal permits Dog, Cat {}
final class Dog implements Animal {}
final class Cat implements Animal {}
final class Bird implements Animal {}

"‘Bird' is not allowed in the sealed hierarchy"</code></pre>
</div>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_java_21">Java 21</h2>
<div class="sectionbody">
<div class="sect2">
<h3 id="_sequencedcollection_interface"><code>SequencedCollection</code> interface</h3>
<div class="paragraph">
<p>Before Java 21 accessing elements in order was not just not straight forward, but some brave people might call it chaos.
With some of the types not having any method to access sequential elements (like <code>getFirst</code>, <code>getLast</code>, <code>reversed</code>),
while others having the same, on top of some these' supertypes / subtypes having methods for that, while others did not.
And even the ones having methods, had separate means of calling those. In short: chaos.</p>
</div>
<div class="paragraph">
<p>With Java 21, the collections implementing sequential elements have to implement the <code>SequentialCollection</code> interface,
making the existence of these methods obvious, and unified.</p>
</div>
<div class="openblock scrollable">
<div class="content">
<table class="tableblock frame-all grid-all stretch">
<colgroup>
<col style="width: 33.3333%;">
<col style="width: 33.3333%;">
<col style="width: 33.3334%;">
</colgroup>
<thead>
<tr>
<th class="tableblock halign-left valign-top">Scala</th>
<th class="tableblock halign-left valign-top">Java (old)</th>
<th class="tableblock halign-left valign-top">Java (new)</th>
</tr>
</thead>
<tbody>
<tr>
<td class="tableblock halign-left valign-top"><div class="content"><div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-scala" data-lang="scala">def doStuff(
  list: List[Int],
  deque: ArrayDeque[Int],
  sortedSet: SortedSet[Int],
  linkedHashSet: LinkedHashSet[Int]
) = {
  var i = 0
  // get first
  i = list.head
  i = deque.head
  i = sortedSet.head
  i = linkedHashSet.head
  // get last
  i = list.last
  i = deque.last
  i = sortedSet.last
  i = linkedHashSet.last
}</code></pre>
</div>
</div></div></td>
<td class="tableblock halign-left valign-top"><div class="content"><div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">void doStuff(
    List&lt;Integer&gt; list,
    Deque&lt;Integer&gt; deque,
    SortedSet&lt;Integer&gt; sortedSet,
    LinkedHashSet&lt;Integer&gt; linkedHashSet
) {
    Integer i;
    // get first
    i = list.get(0);
    i = deque.getFirst();
    i = sortedSet.first();
    i = linkedHashSet.iterator().next();
    // get last
    i = list.get(list.size() - 1);
    i = deque.getLast();
    i = sortedSet.last();
    // i = linkedHashSet.? missing
}</code></pre>
</div>
</div></div></td>
<td class="tableblock halign-left valign-top"><div class="content"><div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">void doStuff2(
    List&lt;Integer&gt; list,
    Deque&lt;Integer&gt; deque,
    SortedSet&lt;Integer&gt; sortedSet,
    LinkedHashSet&lt;Integer&gt; linkedHashSet
) {
    Integer i;
    // get first
    i = list.getFirst();
    i = deque.getFirst();
    i = sortedSet.getFirst();
    i = linkedHashSet.getFirst();
    // get last
    i = list.getLast();
    i = deque.getLast();
    i = sortedSet.getLast();
    i = linkedHashSet.getLast();
}</code></pre>
</div>
</div></div></td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
<div class="sect2">
<h3 id="_pattern_matching_switch">Pattern matching switch</h3>
<div class="paragraph">
<p>Switch expressions were a nice syntactic sugar, but functionality wise they didn&#8217;t come with anything new.
You could still only use primitive types, Strings, or enums, and were only able to match on the concrete value of the input.
With java 21 all that changed, and you can use switch expressions with any types.
In order to actually take advantage of this of course, a lot of new patterns were introduced on top of the value match.</p>
</div>
<div class="ulist">
<ul>
<li>
<p>null pattern<br>
In previous versions if the value was <code>null</code> inside the <code>switch</code>, it would always throw  <code>NullPointerException</code>.
With the new null pattern these exceptions can be caught.</p>
</li>
<li>
<p>type pattern<br>
You can now pattern match for the types. Just like with the pattern matching <code>instanceof</code>,
you can use the new type without any casting necessary.</p>
</li>
<li>
<p>guarded patterns<br>
You can define additional conditions for you patterns. This very well corresponds with the syntax,
previously seen with <code>instanceof</code>, where the matched arguments can already be used as a concrete type in the guards.</p>
</li>
<li>
<p>record deconstruction<br>
You can not only match on <code>records</code> similarly to the type pattern, but it is now possible to deconstruct nested structures,
and match on nested types as well. You can also use the concrete types of these nested values.
That is very powerful with deeply nested structures, where you don&#8217;t need to access a very deep value by hand.<br>
Note, that this new record deconstruction also works with the <code>instanceof</code> operator.</p>
</li>
<li>
<p>sealed class exhaustion<br>
Pattern matching switch is, where the most powerful feature of sealed classes / interfaces come to light.
Because the compiler knows exactly which classes can implement a sealed class, if the input of the switch is a sealed class,
you don&#8217;t need to define a <code>default</code> case, since the compiler is able to tell if the switch is exhaustive or not.
That way, previously existing bugs, of not updating a switch, when e.g. the domain changes are a thing in the past,
because with this new addition the compiler will force you to.</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>There is no point of bringing an old example for this, since it is so different from the core,
you would simply look for another approach in previous java versions.</p>
</div>
<div class="openblock scrollable">
<div class="content">
<table class="tableblock frame-all grid-all stretch">
<colgroup>
<col style="width: 50%;">
<col style="width: 50%;">
</colgroup>
<thead>
<tr>
<th class="tableblock halign-left valign-top">Scala</th>
<th class="tableblock halign-left valign-top">Java (new)</th>
</tr>
</thead>
<tbody>
<tr>
<td class="tableblock halign-left valign-top"><div class="content"><div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-scala" data-lang="scala">case class Wing(length: Int, fact: Option[String])

sealed trait Animal

case class Dog() extends Animal
case class Cat() extends Animal
case class Bird(birdType: String, wing: Wing) extends Animal

def getWingStatus(animal: Animal): String = animal match {
  case null =&gt; "no animal provided"
  case Dog() =&gt; "dogs don't have wings"
  case Cat() =&gt; "cats don't have wings"
  case Bird(_, Wing(_, fact)) if fact.isDefined =&gt; s"interesting fact: ${fact.get}"
  case Bird(_, Wing(_, Some(fact))) =&gt;
    s"interesting fact: ${fact}"
  case Bird(birdType, Wing(length, _)) =&gt;
    s"$birdType has $length long wings"
}</code></pre>
</div>
</div></div></td>
<td class="tableblock halign-left valign-top"><div class="content"><div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">record Wing(Integer length, Optional&lt;String&gt; fact) {}

sealed interface Animal permits Dog, Cat, Bird {}

final class Dog implements Animal {}
final class Cat implements Animal {}
record Bird(String birdType, Wing wing) implements Animal {}

private String getWingStatus(Animal animal) {
    return switch (animal) {
        case null -&gt; "no animal provided";
        case Dog ignored -&gt; "dogs don't have wings";
        case Cat ignored -&gt; "cats don't have wings";
        case Bird(String birdType, Wing(Integer length, Optional&lt;String&gt; fact))
            when fact.isPresent() -&gt; "interesting fact: " + fact.get();
        case Bird(String birdType, Wing(Integer length, Optional&lt;String&gt; fact)) -&gt;
            String.format("%s has %d long wings", birdType, length);
    };
}</code></pre>
</div>
</div></div></td>
</tr>
</tbody>
</table>
</div>
</div>
<div class="paragraph">
<p>You can see, how it is pretty similar now in that exact case. However one must note,
that while this is the new best thing in java, that is just the tip of the iceberg in Scala.</p>
</div>
<div class="paragraph">
<p>You can already see an example for that above, where (right before the guard pattern) the type pattern,
and the literal value pattern is mixed. First the the type <code>Bird</code> is matched,
then the record deconstructed, in a way that it will only match, if the wingfact is present.</p>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_beyond">Beyond</h2>
<div class="sectionbody">
<div class="sect2">
<h3 id="_unnamed_variables_java_22">Unnamed variables (Java 22)</h3>
<div class="paragraph">
<p>A minor improvement in developer experience is introducing unnamed variables.
If you take a look at the previous example for pattern matching, you would notice,
that although the example now looks pretty similar, in case of java you still had to give some name to the variables,
even if you are not using them later on. With the introduction of unnamed variables you can use <code>_</code> as the identifier,
and you can reuse it as many times as you&#8217;d like, and not be able to reference it later.
So it does not clutter up your scope, nor can it overshadow an outside variable by accident.
In short it doesn&#8217;t just signals the implementor&#8217;s intention, but enforces it as well,
making the code safer, and more obvious to read in the future.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">private String getWingStatus(Animal animal) {
    return switch (animal) {
        case null -&gt; "no animal provided";
        case Dog _ -&gt; "dogs don't have wings";
        case Cat _ -&gt; "cats don't have wings";
        case Bird(String _, Wing(Integer _, Optional&lt;String&gt; fact))
            when fact.isPresent() -&gt; "interesting fact: " + fact.get();
        case Bird(String birdType, Wing(Integer length, Optional&lt;String&gt; _)) -&gt;
            String.format("%s has %d long wings", birdType, length);
    };
}</code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="_unnamed_classes_java_22">Unnamed classes (Java 22)</h3>
<div class="paragraph">
<p>With previous versions already enabling running java as a single file, or even as a script,
the need for defining an exact main class is fading. This new feature leverages that thought,
and lets the user create java files without extra boilerplate.</p>
</div>
<div class="openblock scrollable">
<div class="content">
<table class="tableblock frame-all grid-all stretch">
<colgroup>
<col style="width: 50%;">
<col style="width: 50%;">
</colgroup>
<thead>
<tr>
<th class="tableblock halign-left valign-top">Java (old)</th>
<th class="tableblock halign-left valign-top">Java (new)</th>
</tr>
</thead>
<tbody>
<tr>
<td class="tableblock halign-left valign-top"><div class="content"><div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">public class HelloWorldJava8 {
    public static void main(String[] args) {
	    System.out.println("Hello World");
    }
}</code></pre>
</div>
</div></div></td>
<td class="tableblock halign-left valign-top"><div class="content"><div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">void main() {
    System.out.println("Hello World");
}</code></pre>
</div>
</div></div></td>
</tr>
</tbody>
</table>
</div>
</div>
<div class="paragraph">
<p>This makes the learning curve much easier for a newcomer, but also opens the door to even easier scripting in the future.</p>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_closing_thoughts">Closing thoughts</h2>
<div class="sectionbody">
<div class="paragraph">
<p>If now, you feel like Scala is bad, because Java adopted its best features I failed.
If you feel like Java is bad, because it lacks a lot of features Scala has, I also failed.
If you feel like Java is excellent, because it can adopt in an environment, it&#8217;s maybe not that familiar,
and you feel like Scala is excellent, because it can leverage a familiar environment to the fullest,
only then I have truly succeeded.</p>
</div>
<div class="paragraph">
<p>What we need to understand, is the goal of Scala, and Java are two very different things.
Scala is a functional programming language, so the language and its whole ecosystem is designed around that fact,
while java&#8217;s main focus lies rather elsewhere.</p>
</div>
<div class="paragraph">
<p>The fact, that Java recognizes the value in a lot of functional paradigms shows the modern thinking of its maintainers,
and projects a bright future ahead.</p>
</div>
<div class="paragraph">
<p>The fact, that these paradigms are existing, and also well implemented
(even well enough for the <em>old bigbrother</em> java) shows great design from the creators of Scala.</p>
</div>
<div class="paragraph">
<p>Java and Scala, while distinct in their philosophies, have carved out a shared space within the JVM ecosystem,
proving that innovation and tradition can coexist, complement,
and even elevate each other, hence elevate modern software development.</p>
</div>
</div>
</div>
<]]></content:encoded>
					
		
		
			</item>
         
	<item>
		<title>SBT: More than a Build Tool</title>
		<link>https://blog.lunatech.com//posts/2025-02-21-sbt-more-than-a-build-tool</link>
		
		<dc:creator><![CDATA[George]]></dc:creator>
        <pubDate>2025-02-21T00:00:00.000Z</pubDate>
         
             {
            <category><![CDATA[sbt]]></category>
                }
             {
            <category><![CDATA[build-tool]]></category>
                }
             {
            <category><![CDATA[scala]]></category>
                }
             {
            <category><![CDATA[jvm]]></category>
                }
             {
            <category><![CDATA[we-know-scala]]></category>
                }
             {
            <category><![CDATA[scala-lujah]]></category>
                }
             {
            <category><![CDATA[en]]></category>
                }
             
        
		<guid isPermaLink="false">https://blog.lunatech.com//posts/2025-02-21-sbt-more-than-a-build-tool</guid>

					<description>
                        <![CDATA[ Scala Build Tool (SBT) is widely known for compiling, testing, and packaging Scala projects. However, its design as an extensible, programmable tool opens doors to uses beyond traditional build automation. Let's explore SBT's additional functionalities and practical applications.]]></description>
                    <content:encoded><![CDATA[
                    <div class="sect1">
<h2 id="_introduction">Introduction</h2>
<div class="sectionbody">
<div class="paragraph">
<p>Scala Build Tool (SBT) is widely known for compiling, testing, and packaging Scala projects. However, its design as an extensible, programmable tool opens doors to uses beyond traditional build automation. Let&#8217;s explore SBT&#8217;s additional functionalities and practical applications.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_sbt_a_brief_overview">SBT: A Brief Overview</h2>
<div class="sectionbody">
<div class="sect2">
<h3 id="_what_is_sbt">What is SBT?</h3>
<div class="paragraph">
<p>SBT (Scala Build Tool) is the de facto build tool for Scala projects. It&#8217;s an open-source build tool written in Scala that provides a Domain-Specific Language (DSL) for describing build configurations. SBT offers interactive capabilities, incremental compilation, and continuous compilation features. It uses Scala code for build definitions, allowing developers to leverage the full power of the Scala language in their build processes.</p>
</div>
</div>
<div class="sect2">
<h3 id="_sbt_vs_traditional_build_tools">SBT vs Traditional Build Tools</h3>
<div class="paragraph">
<p>SBT is specifically designed for Scala projects, with deep integration into the Scala ecosystem. While it can handle Java code within Scala projects, it&#8217;s not typically used for pure Java projects where tools like Maven and Gradle are more appropriate.</p>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_practical_applications_of_sbt">Practical Applications of SBT</h2>
<div class="sectionbody">
<div class="sect3">
<h4 id="_simple_configuration">Simple Configuration</h4>
<div class="paragraph">
<p>SBT follows "convention over configuration" principles. For basic Scala projects, you might only need a few lines in your <code>build.sbt</code> file.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-scala" data-lang="scala">name := "my-project"
version := "1.0"
scalaVersion := "2.13.10"</code></pre>
</div>
</div>
</div>
<div class="sect3">
<h4 id="_scala_based_build_definition">Scala-Based Build Definition</h4>
<div class="paragraph">
<p>Unlike XML-based build tools, SBT lets you write your build configuration in Scala. This means you can use variables, functions, and even complex logic in your build definitions, making them more maintainable and powerful.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-scala" data-lang="scala">val commonSettings = Seq(
  organization := "com.example",
  version := "1.0",
  scalaVersion := "2.13.10"
)

lazy val core = (project in file("core"))
  .settings(commonSettings)
  .settings(
    name := "my-core-project",
    libraryDependencies += "org.typelevel" %% "cats-core" % "2.9.0"
  )</code></pre>
</div>
</div>
</div>
<div class="sect3">
<h4 id="_incremental_compilation">Incremental Compilation</h4>
<div class="paragraph">
<p>SBT tracks dependencies between your source files and only recompiles what&#8217;s necessary. When you change a file, SBT analyzes its dependencies and recompiles only affected files, significantly reducing build times.</p>
</div>
</div>
<div class="sect3">
<h4 id="_library_management">Library Management</h4>
<div class="paragraph">
<p>Using Coursier as its dependency resolver, SBT efficiently handles library dependencies, resolving and downloading them from repositories. It manages transitive dependencies and version conflicts automatically.</p>
</div>
</div>
<div class="sect3">
<h4 id="_continuous_compilation">Continuous Compilation</h4>
<div class="paragraph">
<p>With the <code>~</code> command prefix, SBT watches your source files and automatically recompiles when changes are detected. This creates a rapid development cycle, perfect for interactive development.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-console" data-lang="console">// Watch and recompile
$ sbt "~compile"

// Watch and run tests
$ sbt "~test"

// Watch specific test
$ sbt "~testOnly com.example.MySpec"</code></pre>
</div>
</div>
</div>
<div class="sect3">
<h4 id="_mixed_scalajava_support">Mixed Scala/Java Support</h4>
<div class="paragraph">
<p>SBT seamlessly handles projects containing both Scala and Java code, automatically detecting and compiling both languages while maintaining proper dependency ordering.</p>
</div>
</div>
<div class="sect3">
<h4 id="_testing_framework_integration">Testing Framework Integration</h4>
<div class="paragraph">
<p>Built-in support for major Scala testing frameworks means you can run tests directly from SBT. It integrates with ScalaTest, specs2, and ScalaCheck out of the box, with plugin support for JUnit.</p>
</div>
</div>
<div class="sect3">
<h4 id="_interactive_scala_repl">Interactive Scala REPL</h4>
<div class="paragraph">
<p>Launch a Scala REPL session with your project&#8217;s classes and dependencies already loaded, perfect for exploring and testing code interactively.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-scala" data-lang="scala">// In your project
case class User(name: String, age: Int)
class UserService {
  def greet(user: User) = s"Hello, ${user.name}!"
}

// In the REPL (after running 'sbt console')
scala&gt; val user = User("Alice", 25)
user: User = User(Alice,25)

scala&gt; val service = new UserService
service: UserService = UserService@1234abcd

scala&gt; service.greet(user)
res0: String = Hello, Alice!</code></pre>
</div>
</div>
</div>
<div class="sect3">
<h4 id="_project_modularization">Project Modularization</h4>
<div class="paragraph">
<p>Break down complex projects into manageable sub-projects, each with its own dependencies and configurations, while maintaining build coordination across the entire project.</p>
</div>
</div>
<div class="sect3">
<h4 id="_external_project_dependencies">External Project Dependencies</h4>
<div class="paragraph">
<p>Reference other Git repositories directly as dependencies, enabling seamless integration with external projects and custom forks of libraries.</p>
</div>
</div>
<div class="sect3">
<h4 id="_parallel_execution">Parallel Execution</h4>
<div class="paragraph">
<p>Speed up builds and tests by running independent tasks in parallel, taking advantage of multiple CPU cores for faster build times. By default SBT runs tasks in parallel and tests in sequence. You can change this behavior by configuring the build.sbt file by either enablig test parallelism and adjusting the parallel execution settings, such as limiting the number of cores used for example.</p>
</div>
</div>
<div class="sect2">
<h3 id="_beyond_build_tool_features">Beyond Build Tool Features</h3>
<div class="sect3">
<h4 id="_custom_task_creation">Custom Task Creation</h4>
<div class="paragraph">
<p>SBT allows you to define custom tasks for any purpose - from deploying applications to generating documentation. You can create tasks that integrate with external services, process data, or automate any development workflow.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-scala" data-lang="scala">// Define individual tasks
lazy val startDb = taskKey[Unit]("Starts the database")
startDb := {
  "docker-compose up -d postgres".!
}

lazy val runMigrations = taskKey[Unit]("Runs database migrations")
runMigrations := Def.sequential(
  startDb,                // Start database first
  flywayClean,           // Clean database schema
  flywayMigrate          // Run Flyway migrations
).value</code></pre>
</div>
</div>
</div>
<div class="sect3">
<h4 id="_development_workflow_automation">Development Workflow Automation</h4>
<div class="paragraph">
<p>Use SBT as a complete development environment orchestrator. Create custom commands to start databases, mock services, or set up entire development environments with a single command.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-scala" data-lang="scala">// Combine previously defined tasks into a workflow
lazy val startLocalEnv = taskKey[Unit]("Start local development environment")
startLocalEnv := Def.sequential(
  runMigrations,         // Run database migrations
  (Compile / run)        // Finally start the application
).value</code></pre>
</div>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-console" data-lang="console">// Use it with:
&gt; sbt startLocalEnv  // Executes all tasks in sequence</code></pre>
</div>
</div>
</div>
<div class="sect3">
<h4 id="_code_generation">Code Generation</h4>
<div class="paragraph">
<p>Leverage SBT&#8217;s source generators to automatically create code, such as generating case classes from database schemas, creating TypeScript definitions from Scala classes, or producing API documentation.</p>
</div>
</div>
<div class="sect3">
<h4 id="_database_migration">Database Migration</h4>
<div class="paragraph">
<p>Through plugins like Flyway or Slick-migration, SBT can manage database schemas and migrations, making it a powerful tool for database version control and deployment.</p>
</div>
<div class="paragraph">
<p>Using the SBT Flyway plugin:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-scala" data-lang="scala">// In plugins.sbt
addSbtPlugin("io.github.davidmweber" % "flyway-sbt" % "7.4.0")

// In build.sbt
flywayConfigFiles := Seq("flyway-e2e.conf")</code></pre>
</div>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-console" data-lang="console">&gt; sbt flywayMigrate    // Using the SBT plugin</code></pre>
</div>
</div>
</div>
<div class="sect3">
<h4 id="_documentation_generation">Documentation Generation</h4>
<div class="paragraph">
<p>Beyond API docs, SBT can generate various types of documentation, from project websites to technical specifications, using plugins like sbt-site, ScalaDoc or mdoc.</p>
</div>
<div class="paragraph">
<p>A common example using ScalaDoc:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-scala" data-lang="scala">// In build.sbt
Compile / doc / scalacOptions ++= Seq(
  "-groups",
  "-doc-title", "My Project Documentation"
)</code></pre>
</div>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-console" data-lang="console">// Generate documentation with:
&gt; sbt doc  // Creates ScalaDoc in target/scala-2.13/api/</code></pre>
</div>
</div>
</div>
<div class="sect3">
<h4 id="_release_management">Release Management</h4>
<div class="paragraph">
<p>SBT can handle the entire release process, including version bumping, changelog generation, Git tagging, and publishing to various repositories or platforms.</p>
</div>
</div>
<div class="sect3">
<h4 id="_quality_analysis">Quality Analysis</h4>
<div class="paragraph">
<p>Integrate with code quality tools to analyze source code, check coverage, enforce styling rules, and generate quality reports as part of your development workflow.</p>
</div>
<div class="paragraph">
<p>For example, to check code coverage in your project, first add the scoverage plugin to your <code>project/plugins.sbt</code>:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-scala" data-lang="scala">addSbtPlugin("org.scoverage" % "sbt-scoverage" % "2.0.9")</code></pre>
</div>
</div>
<div class="paragraph">
<p>Then you can run coverage analysis:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-console" data-lang="console">&gt; sbt coverage         // Enable code coverage tracking
&gt; sbt test            // Run your tests - this collects coverage data
&gt; sbt coverageReport  // Generate coverage report showing which code was tested</code></pre>
</div>
</div>
<div class="paragraph">
<p>The report will be generated in <code>target/scala-2.13/scoverage-report/</code> and includes:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>HTML reports showing line-by-line coverage</p>
</li>
<li>
<p>Overall coverage statistics</p>
</li>
<li>
<p>Highlighted source code showing covered/uncovered lines</p>
</li>
</ul>
</div>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_conclusion">Conclusion</h2>
<div class="sectionbody">
<div class="paragraph">
<p>SBT is a powerful tool that transcends its role as a build tool, offering developers a versatile platform for managing, automating, and enhancing their development workflows. Whether you’re working on a small library or a large-scale application, SBT’s features and extensibility make it a valuable addition to the Scala ecosystem. SBT acts more as a development platform than a build tool and by understanding its capabilities and limitations, teams can leverage SBT to streamline their processes and focus on building great software.</p>
</div>
</div>
</div>
<]]></content:encoded>
					
		
		
			</item>
         
	<item>
		<title>Interop Summit. Why do we only import Java libraries?</title>
		<link>https://blog.lunatech.com//posts/2025-02-14-interop-summit</link>
		
		<dc:creator><![CDATA[Konstantin Kolmar]]></dc:creator>
        <pubDate>2025-02-14T00:00:00.000Z</pubDate>
         
             {
            <category><![CDATA[jvm]]></category>
                }
             {
            <category><![CDATA[interop]]></category>
                }
             {
            <category><![CDATA[scala]]></category>
                }
             {
            <category><![CDATA[scala3]]></category>
                }
             {
            <category><![CDATA[kotlin]]></category>
                }
             {
            <category><![CDATA[gradle]]></category>
                }
             {
            <category><![CDATA[groovy]]></category>
                }
             {
            <category><![CDATA[we-know-scala]]></category>
                }
             {
            <category><![CDATA[scala-lujah]]></category>
                }
             {
            <category><![CDATA[en]]></category>
                }
             
        
		<guid isPermaLink="false">https://blog.lunatech.com//posts/2025-02-14-interop-summit</guid>

					<description>
                        <![CDATA[ The Java platform, including the Java language and Java Virtual Machine (JVM), was first released around 1995. At that time, Java was the only language running on the JVM. Soon, however, other languages followed, which addressed some of Java’s shortcomings while still leveraging its runtime and the vast collection of standard and third-party libraries and allowing integration with a large amount of existing Java code.]]></description>
                    <content:encoded><![CDATA[
                    <div class="sect1">
<h2 id="_short_history_of_the_java_platform">Short history of the Java platform</h2>
<div class="sectionbody">
<div class="paragraph">
<p>The Java platform, including the Java language and Java Virtual Machine (JVM), was first released around 1995. At that time, Java was the only language running on the JVM. Soon, however, other languages followed, which addressed some of Java’s shortcomings while still leveraging its runtime and the vast collection of standard and third-party libraries and allowing integration with a large amount of existing Java code.</p>
</div>
<div class="paragraph">
<p>Scala was one of the first such languages. Its development started in 2001, and the first release came out in 2004. Its main goal was to mix functional and object-oriented programming and to allow writing more concise code than Java.</p>
</div>
<div class="paragraph">
<p>Groovy was released in 2007 and introduced dynamic typing and improved scripting capabilities. Clojure also came out in 2007. As a Lisp dialect, its strengths lie in functional programming and metaprogramming.</p>
</div>
<div class="paragraph">
<p>Kotlin was one of the later major languages that entered the scene. Its implementation started in 2010, and the first stable release was in 2016. Kotlin was designed to be a nicer Java with seamless interoperability. Later, it became officially supported for Android development.</p>
</div>
<div class="paragraph">
<p>It is interesting to note that no new major languages have appeared in about 15 years now. This is probably because existing languages already cover the most important niches. Moreover, Java now includes quality-of-life features like lambdas, closures, lazy streams, records, and virtual threads, which had previously motivated the creation of new languages. Nowadays you would also need a large amount of tooling and libraries to support a new language, and probably some killer application or support and promotion from a large company.</p>
</div>
<div class="paragraph">
<p>Still, there is a large variety of less prominent languages on the JVM, including even some internal company languages. Many originally non-JVM languages have compilers that target JVM such as Jython for Python.</p>
</div>
<div class="paragraph">
<p>But given the large variety of available options, why do we only import libraries implemented in Java or in the language we are using? Well, it&#8217;s probably not a huge mystery. I bet you can name several important reasons yourself. But I think it&#8217;s still interesting to think about, so let&#8217;s review some of them.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_1_utility_libraries_are_implemented_in_each_language">1. Utility libraries are implemented in each language</h2>
<div class="sectionbody">
<div class="paragraph">
<p>Small or utility libraries are simply implemented natively in each language to provide idiomatic APIs. Such implementations might be a part of the standard library or provided by third parties. A good example is JSON processing. There are a lot of third-party JSON libraries in Scala, often using typeclasses and other special Scala features. In contrast, in Kotlin JSON is supported by an official library in <a href="https://github.com/Kotlin/kotlinx.serialization">kotlinx.serialization</a>. There is a similar situation with idiomatic libraries for dependency injection, web frameworks, and so on.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_2_few_large_unique_libraries">2. Few large unique libraries</h2>
<div class="sectionbody">
<div class="paragraph">
<p>There is a lack of genuine need to import anything large from outside. What libraries unique to Kotlin, let alone other non-Java languages, would you want to use in your Scala code? Jetpack Compose is an example of a Kotlin library occupying a unique niche. It is the de facto default GUI framework on Android. However, since it&#8217;s a GUI framework you wouldn’t normally import it as a library, and you rarely see Scala code on Android anyway.</p>
</div>
<div class="paragraph">
<p>As for Scala, there are unique libraries that could be useful in Java or Kotlin code: Akka or Pekko, Spark, Gatling, or Flink. But they usually already provide bindings or APIs for Java, so you don&#8217;t need their Scala APIs. Many of them are even discontinuing their Scala API, or avoiding migration to Scala 3.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_3_focus_on_using_java_code">3. Focus on using Java code</h2>
<div class="sectionbody">
<div class="paragraph">
<p>Java is one of the most popular languages ever created, so over its long history a lot of libraries for all kinds of purposes have been produced. This means that language authors of every JVM language make a special effort to provide an easy way to interact with Java dependencies.</p>
</div>
<div class="paragraph">
<p>The end result is that using Java code from Scala or Kotlin is fairly simple. You can call methods normally and give them arguments, extend classes and interfaces, and so on. Scala standard library supplies a <code>scala.jdk</code> package, that contains many facilities to assist with interoperability.</p>
</div>
<div class="paragraph">
<p>Of course, this is still not always completely straightforward. One obvious point of contention is nullability. When using Java libraries from Scala you usually need to wrap nearly everything in an <code>Option</code> to avoid null pointer exceptions. You may say that using Java libraries is not idiomatic, but even in the standard library, there are packages you may want to use occasionally: <code>java.nio.file</code>, <code>java.time</code>, Unicode support, and so on.</p>
</div>
<div class="paragraph">
<p>Here is an example of a Scala 3 extension to wrap the result of one Java method:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-scala" data-lang="scala">extension (p: Path)
  def parent: Option[Path] = Option(p.getParent)</code></pre>
</div>
</div>
<div class="paragraph">
<p>This approach is not ideal, because if you miss any wrappers, you&#8217;ll get a <code>NullPointerException</code> at runtime.</p>
</div>
<div class="paragraph">
<p>Scala 3 has added union types, so now you can declare nullable types directly: <code>MyType | Null</code>. It also has the <a href="https://docs.scala-lang.org/scala3/reference/experimental/explicit-nulls.html">explicit nulls</a> feature enabled by the <code>-Yexplicit-nulls</code> flag. This means that all values that can have a <code>null</code> value, including all values coming from Java, must have a nullable type. This reduces the <code>Option</code> boilerplate when dealing with Java code, but introduces a different kind of boilerplate: null-checking the results of functions that can never return null.</p>
</div>
<div class="paragraph">
<p>To improve this the recently released Scala 3.5 has introduced <a href="https://docs.scala-lang.org/scala3/reference/experimental/explicit-nulls.html#java-interoperability-and-flexible-types-1">flexible types</a> inspired by Kotlin&#8217;s <a href="https://kotlinlang.org/docs/java-interop.html#null-safety-and-platform-types">platform types</a>. This feature is enabled by default but can be turned off with the <code>-Yno-flexible-types</code> flag. It means that values coming from Java can now be treated as either nullable or non-nullable. This offers the same safety guarantees as Java, so again it has reverted to the <code>Option</code> wrapper situation, and it&#8217;s possible to get null pointer exceptions again.</p>
</div>
<div class="paragraph">
<p>This development process demonstrates both how much effort forward interop receives and how hard it is to provide a good solution for some issues. Well, nulls wouldn&#8217;t have been a billion-dollar mistake otherwise.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_4_reverse_interoperability_is_complicated">4. Reverse interoperability is complicated</h2>
<div class="sectionbody">
<div class="paragraph">
<p>Reverse interoperability refers to tools and techniques that allow developers to write code accessible from Java and potentially other JVM languages. However, it can be difficult to transparently incorporate features that are unique to a particular language. For instance, when calling Scala code from Java, implicit values must be explicitly constructed, which undermines the usability of the API.</p>
</div>
<div class="paragraph">
<p>Even in simpler cases reverse interoperability requires carefully marking your code with annotations or using some non-idiomatic constructs. For example:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-scala" data-lang="scala">case class MountainRange(mountains: List[Mountain])
object MountainRange:
  @varargs
  @targetName("of3")
  @throws[IllegalArgumentException]
  def ^^^(mountains: Mountain*): MountainRange = {
    if (mountains.size != 3) throw IllegalArgumentException("Incorrect number of mountains")
    MountainRange(mountains.toList)
  }</code></pre>
</div>
</div>
<div class="paragraph">
<p>The annotations in this method cause the Scala compiler to produce a signature that can better interact with Java. <code>@varargs</code> means that the argument will be a Java <code>Array</code> instead of a Scala <code>Seq</code>, <code>targetName</code> gives it a stable alphanumeric name instead of a technical name mangled by the compiler, and <code>@throws</code> adds the corresponding "throws" declaration to the method signature.</p>
</div>
<div class="paragraph">
<p>Another interesting example that demonstrates how much of an afterthought reverse interop can be is trying to define an enumeration that extends <code>java.lang.Enum</code>. In Scala 3 this is straightforward:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-scala" data-lang="scala">enum Mountain extends Enum[Mountain]:
  case Everest, Kilimanjaro, MontBlanc, Fujiyama</code></pre>
</div>
</div>
<div class="paragraph">
<p>Scala 3 compiler automatically generates calls to the <code>java.lang.Enum</code> constructor to initialize the values. But I don&#8217;t know a way to create a Java-compatible enumeration from Scala 2. Maybe it&#8217;s not possible at all!</p>
</div>
<div class="paragraph">
<p>Other features reverse interoperability has to handle may include:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>Static methods and constant values.</p>
</li>
<li>
<p>Class fields, getters, and setters, because many JVM languages try to improve their handling in some way.</p>
</li>
<li>
<p>Optional method arguments and default values. Java doesn&#8217;t allow those, but most other JVM languages do.</p>
</li>
<li>
<p>Different visibility modes, such as Scala&#8217;s <code>sealed</code> or Kotlin&#8217;s <code>internal</code>.</p>
</li>
<li>
<p>Concurrency primitives. Every language has something unique and barely compatible with each other. For example, Scala uses Futures or various IO libraries, Kotlin has coroutines in its standard library, and Java has recently added virtual threads.</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>Imagine having to support this menagerie for multiple languages, each with its own assumptions and idioms, changing and updating over time. If every language provided bindings or APIs for every other language, the complexity would explode.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_5_concerns_about_runtime_dependencies">5. Concerns about runtime dependencies</h2>
<div class="sectionbody">
<div class="paragraph">
<p>Using libraries from another language usually implies including that language&#8217;s standard library as a runtime dependency. This slows down the build and increases distribution sizes. The effect may not be large in absolute terms, but still provides enough incentive for library authors to design their libraries to avoid unnecessary dependencies on the entire standard library of a whole language.</p>
</div>
<div class="paragraph">
<p>As a consequence of those reasons Java naturally serves as the common denominator to mediate between JVM languages.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_case_study">Case study</h2>
<div class="sectionbody">
<div class="paragraph">
<p>Situations where you need to interact between non-Java languages do happen but are fairly unusual. One interesting example from our team involved configuring access to intranet repositories (without internet access) in our Gradle builds.</p>
</div>
<div class="paragraph">
<p>Let&#8217;s adopt the following assumptions:</p>
</div>
<div class="olist arabic">
<ol class="arabic">
<li>
<p>We are using Kotlin for our Gradle builds, because Kotlin is statically typed and its tooling and IDE support are better than Groovy’s.</p>
</li>
<li>
<p>Multiple teams publish their artifacts into their own repositories on the shared Artifactory. Different projects need different dependencies, so our goal is to give the project maintainers a simple way to add the repositories with the artifacts they need. We want to have an extension method on the <code>RepositoryHandler</code>, similar to the idiomatic Gradle methods such as <code>mavenCentral()</code> or <code>gradlePluginPortal()</code>:</p>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-kotlin" data-lang="kotlin">repositories { // this: RepositoryHandler =&gt;
    mavenInternal("maven-releases")
    mavenInternal("gradle-plugins")
    mavenInternal("other-team-artifacts")
}</code></pre>
</div>
</div>
</li>
<li>
<p>We have a local plugin to set the repository URL and configure a way to obtain a login token from the environment:</p>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-groovy" data-lang="groovy">def extendRepositories(RepositoryHandler repositories) {
    if (repositories !instanceof ExtensionAware) return

    repositories.ext {
        mavenInternal = { repoName -&gt;
            repositories.maven {
                name = repoName
                url = "https://artifactory.example.com/$repoName"
                credentials {
                    token = providers.environmentVariable("ARTIFACTORY_TOKEN")
                            .orElse(providers.systemProperty("gradle.wrapperPassword"))
                            .orNull
                }
            }
        }
    }
}</code></pre>
</div>
</div>
</li>
</ol>
</div>
<div class="paragraph">
<p>The problem here is that Gradle can automatically execute Groovy builds, but for Kotlin builds it needs to download a special plugin, and to download the plugin without internet access, it requires the internal repository to be already configured, creating a Catch-22 type of problem. This means the repository configuration plugin above has to be implemented in Groovy.</p>
</div>
<div class="paragraph">
<p>In the Groovy build flavor, you can directly use methods defined in an <a href="https://docs.gradle.org/current/dsl/org.gradle.api.plugins.ExtraPropertiesExtension.html">extra properties extension</a>. But Kotlin doesn&#8217;t understand that approach. It can&#8217;t interact with standard Groovy extension methods either. Groovy implements them by modifying Groovy metaclasses, but in Kotlin extension methods are just syntax sugar, and at runtime are implemented as normal methods taking the receiver as the first argument.</p>
</div>
<div class="paragraph">
<p>In the end, the solution was to create an intermediate plugin in Kotlin, that provides a Kotlin-style extension method. It extracts Groovy <code>Closure</code> from the extra properties extension, casts it to the appropriate type, and calls it using Groovy API:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-kotlin" data-lang="kotlin">fun RepositoryHandler.mavenInternal(path: String) {
    ((this as ExtensionAware).extra["mavenInternal"] as Closure&lt;*&gt;).call(path)
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>This is still not ideal, because this helper method can&#8217;t be shared between the intermediate plugin build and implementation, so it has to be copy-pasted into several places. Nevertheless, this achieves the goal of having nice repository declarations in the user-level Kotlin build.</p>
</div>
<div class="paragraph">
<p>This is an example of how convoluted interoperability can look when assumptions and idioms from different languages and libraries come in conflict with each other.</p>
</div>
</div>
</div>
<]]></content:encoded>
					
		
		
			</item>
         
	<item>
		<title>Recap of the Joy of Coding Meetup at Lunatech</title>
		<link>https://blog.lunatech.com//posts/2025-02-13-joy-of-coding-at-lunatech</link>
		
		<dc:creator><![CDATA[]]></dc:creator>
        <pubDate>2025-02-13T00:00:00.000Z</pubDate>
         
             {
            <category><![CDATA[documentation]]></category>
                }
             {
            <category><![CDATA[automation]]></category>
                }
             {
            <category><![CDATA[opentelemetry]]></category>
                }
             {
            <category><![CDATA[monitoring]]></category>
                }
             {
            <category><![CDATA[grafana]]></category>
                }
             {
            <category><![CDATA[performance]]></category>
                }
             {
            <category><![CDATA[en]]></category>
                }
             
        
		<guid isPermaLink="false">https://blog.lunatech.com//posts/2025-02-13-joy-of-coding-at-lunatech</guid>

					<description>
                        <![CDATA[ On February 12th, Lunatech had the privilege of hosting the Joy of Coding meetup at our office in Rotterdam.]]></description>
                    <content:encoded><![CDATA[
                    <div class="sect1">
<h2 id="_introduction">Introduction</h2>
<div class="sectionbody">
<div class="paragraph">
<p>On February 12th, Lunatech had the privilege of hosting the Joy of Coding meetup at our office in Rotterdam.</p>
</div>
<div class="paragraph">
<p>We were excited to bring developers from across the city together to reconnect and share knowledge in an open and welcoming environment.</p>
</div>
<div class="paragraph">
<p>The evening began with a warm welcome, giving attendees the opportunity to mingle over delicious pizza. With the room buzzing with conversation, it was clear that everyone was eager to dive into the evening’s insightful sessions.</p>
</div>
<div class="imageblock">
<div class="content">
<img src="../media/2025-02-13-joy-of-coding-at-lunatech/networking.png" alt="Introduction over pizza" width="600">
</div>
<div class="title">Figure 1. Introduction over pizza</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_coding_your_documentation">Coding Your Documentation</h2>
<div class="sectionbody">
<div class="paragraph">
<p>The first session of the evening, "Coding Your Documentation" by Hubert Klein Ikkink, explored how developers can take a structured and automated approach to documentation.</p>
</div>
<div class="paragraph">
<p>Writing documentation is often seen as a tedious task, but Hubert demonstrated how code-driven techniques can make the process more efficient, maintainable, and even enjoyable.</p>
</div>
<div class="paragraph">
<p>Through practical examples, the session covered strategies such as using markup languages, automation tools, and integrating documentation directly into the development workflow. Hubert showcased how well-documented projects not only improve collaboration within teams but also enhance the onboarding process for new developers and contribute to overall software quality.</p>
</div>
<div class="paragraph">
<p>Attendees walked away with actionable insights on how to streamline documentation efforts, ensuring that code remains well-documented without slowing down development. The talk was a great reminder that good documentation is just as important as the code itself.</p>
</div>
<div class="imageblock">
<div class="content">
<img src="../media/2025-02-13-joy-of-coding-at-lunatech/documentation.png" alt="Coding Your Documentation" width="600">
</div>
<div class="title">Figure 2. Coding Your Documentation</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_reaching_operational_excellence_using_opentelemetry">Reaching Operational Excellence Using OpenTelemetry</h2>
<div class="sectionbody">
<div class="paragraph">
<p>Riccardo Lippolis took the stage to talk about OpenTelemetry and its critical role in ensuring operational excellence. His session, "Reaching Operational Excellence Using OpenTelemetry," focused on how developers can easily implement standardized APIs for logging and metrics across distributed services.</p>
</div>
<div class="paragraph">
<p>Through practical demonstrations, attendees learned how OpenTelemetry allows for seamless service monitoring, making it easier to identify and solve issues in a production environment. This session provided valuable insights that our community can apply directly to their own work.</p>
</div>
<div class="imageblock">
<div class="content">
<img src="../media/2025-02-13-joy-of-coding-at-lunatech/telemetry.png" alt="Reaching Operational Excellence Using OpenTelemetry" width="600">
</div>
<div class="title">Figure 3. Reaching Operational Excellence Using OpenTelemetry</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_networking_and_drinks">Networking and Drinks</h2>
<div class="sectionbody">
<div class="paragraph">
<p>As the talks concluded, the evening wrapped up with drinks and a networking session, giving everyone the opportunity to continue their conversations, exchange ideas, and make new connections.</p>
</div>
<div class="paragraph">
<p>The atmosphere was energizing, and it was clear that the local developer community is eager to keep pushing the boundaries of tech.</p>
</div>
<div class="paragraph">
<p>See you at the next meetup!</p>
</div>
</div>
</div>
<]]></content:encoded>
					
		
		
			</item>
         
	<item>
		<title>ZGC vs G1GC for Scala</title>
		<link>https://blog.lunatech.com//posts/2025-02-07-zgc-vs-g1gc-for-scala</link>
		
		<dc:creator><![CDATA[Utku Aydın]]></dc:creator>
        <pubDate>2025-02-07T00:00:00.000Z</pubDate>
         
             {
            <category><![CDATA[zgc]]></category>
                }
             {
            <category><![CDATA[gen-zgc]]></category>
                }
             {
            <category><![CDATA[g1]]></category>
                }
             {
            <category><![CDATA[g1gc]]></category>
                }
             {
            <category><![CDATA[scala]]></category>
                }
             {
            <category><![CDATA[jvm]]></category>
                }
             {
            <category><![CDATA[we-know-scala]]></category>
                }
             {
            <category><![CDATA[scala-lujah]]></category>
                }
             {
            <category><![CDATA[en]]></category>
                }
             
        
		<guid isPermaLink="false">https://blog.lunatech.com//posts/2025-02-07-zgc-vs-g1gc-for-scala</guid>

					<description>
                        <![CDATA[ When it comes to high-performance Scala applications, memory management plays a crucial role in maintaining efficiency and stability. The JVM's Garbage Collection (GC) mechanisms help developers avoid memory leaks and memory management while balancing latency and throughput. Two prominent GC strategies—Garbage First (G1GC) and Z Garbage Collector (ZGC)—offer different benefits depending on application needs. In this post, we'll explore these two GC approaches, their configurations, benchmarks, and best-use scenarios for Scala applications.]]></description>
                    <content:encoded><![CDATA[
                    <div class="sect1">
<h2 id="_introduction">Introduction</h2>
<div class="sectionbody">
<div class="paragraph">
<p>When it comes to high-performance Scala applications, memory management plays a crucial role in maintaining efficiency and stability. The JVM&#8217;s Garbage Collection (GC) mechanisms help developers avoid memory leaks and memory management while balancing latency and throughput. Two prominent GC strategies—Garbage First (G1GC) and Z Garbage Collector (ZGC)—offer different benefits depending on application needs. In this post, we&#8217;ll explore these two GC approaches, their configurations, benchmarks, and best-use scenarios for Scala applications.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_garbage_first_gc_g1gc">Garbage First GC (G1GC)</h2>
<div class="sectionbody">
<div class="sect2">
<h3 id="_what_is_g1gc">What is G1GC?</h3>
<div class="paragraph">
<p>G1GC was introduced in JDK 7 and became the default GC in JDK 9. It&#8217;s designed to optimize both latency and throughput by dividing the heap into regions and prioritizing the collection of those with the most garbage. Unlike traditional GC methods, G1GC performs concurrent marking to reduce stop-the-world pauses, enhancing application performance.</p>
</div>
</div>
<div class="sect2">
<h3 id="_when_to_use_g1gc">When to Use G1GC</h3>
<div class="ulist">
<ul>
<li>
<p>G1GC should be used in applications that require predictable pause times.</p>
</li>
<li>
<p>It is suitable for systems where throughput is more critical than achieving ultra-low latency.</p>
</li>
</ul>
</div>
</div>
<div class="sect2">
<h3 id="_when_not_to_use_g1gc">When Not to Use G1GC</h3>
<div class="ulist">
<ul>
<li>
<p>G1GC is not ideal for applications with very large heaps that exceed a few hundred gigabytes.</p>
</li>
<li>
<p>It should be avoided in workloads with extreme garbage generation, as pause times may increase in edge cases.</p>
</li>
</ul>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_z_garbage_collector_zgc">Z Garbage Collector (ZGC)</h2>
<div class="sectionbody">
<div class="sect2">
<h3 id="_what_is_zgc">What is ZGC?</h3>
<div class="paragraph">
<p>ZGC, introduced in JDK 11, is a low-latency garbage collector designed to maintain sub-millisecond pause times regardless of heap size. It performs most of its work concurrently, including marking and compaction, ensuring minimal disruption to application performance. It ZGC can handle heap sizes up to 16 terabytes, making it an excellent choice for large-scale applications.</p>
</div>
</div>
<div class="sect2">
<h3 id="_when_to_use_zgc">When to Use ZGC</h3>
<div class="ulist">
<ul>
<li>
<p>ZGC is recommended for real-time systems that have strict latency requirements.</p>
</li>
<li>
<p>It is well-suited for applications that require efficient scalability with very large heaps.</p>
</li>
</ul>
</div>
</div>
<div class="sect2">
<h3 id="_when_not_to_use_zgc">When Not to Use ZGC</h3>
<div class="ulist">
<ul>
<li>
<p>ZGC should not be used in applications that are constrained by CPU resources.</p>
</li>
<li>
<p>It is not ideal for workloads where high throughput is more critical than maintaining low latency.</p>
</li>
</ul>
</div>
</div>
<div class="sect2">
<h3 id="_generational_zgc_the_cherry_on_top">Generational ZGC: The Cherry on Top</h3>
<div class="paragraph">
<p>Generational ZGC introduces separate young and old generations, optimizing memory reclamation by focusing on short-lived objects more frequently. This approach reduces the overhead associated with managing short-lived objects, which are common in most workloads. Additionally, it further minimizes CPU and memory bandwidth usage compared to the non-generational ZGC. Despite these optimizations, Generational ZGC retains its ultra-low pause times, remaining in the sub-millisecond range. It continues to efficiently handle large heaps, with multi-terabyte support still intact. Like its predecessor, Generational ZGC performs marking, relocation, and compaction concurrently, making sure there are no disruptions in application performance.</p>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_configuring_scala_applications_for_gc">Configuring Scala Applications for GC</h2>
<div class="sectionbody">
<div class="paragraph">
<p>To configure GC in Scala applications, appropriate Java options should be set in build.sbt.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-scala" data-lang="scala">javaOpts += "-XX:+UseZGC -XX:+ZGenerational"</code></pre>
</div>
</div>
<div class="paragraph">
<p>In container environments, the configuration can be achieved by including the required flags in the java options environment variable (may vary between JDK distributions).</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-console" data-lang="console">JAVA_OPTS = "-XX:+UseZGC -XX:+ZGenerational …"</code></pre>
</div>
</div>
<div class="paragraph">
<p>Both garbage collectors also have additional flags that can be included to further fine tune their behavior depending on the use case. These are available in their respective documentation.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_benchmarking_g1gc_vs_zgc">Benchmarking G1GC vs ZGC</h2>
<div class="sectionbody">
<div class="sect2">
<h3 id="_setup">Setup</h3>
<div class="ulist">
<ul>
<li>
<p>The benchmarking tests were conducted in a Kubernetes cluster with 2 CPUs and 4GB of memory allocated.</p>
</li>
<li>
<p>Java options were pre-configured specifically for G1GC and Generational ZGC to ensure accurate comparisons.</p>
</li>
<li>
<p>The test workload consisted of a streaming application that processed messages at varying rates of 300, 600, and 900 messages per second.</p>
</li>
<li>
<p>Each test run included a warm-up phase lasting 10 minutes to allow the system to reach a stable state.</p>
</li>
<li>
<p>Following the warm-up, data recording was conducted for 20 minutes to capture performance metrics.</p>
</li>
</ul>
</div>
</div>
<div class="sect2">
<h3 id="_observations">Observations</h3>
<div class="sect3">
<h4 id="_300_messages_per_second_g1">300 messages per second G1</h4>
<div class="imageblock">
<div class="content">
<img src="../media/2025-02-07-zgc-vs-g1gc-for-scala/300-g1.png" alt="300 G1" width="600">
</div>
</div>
</div>
<div class="sect3">
<h4 id="_300_messages_per_second_zgc">300 messages per second ZGC</h4>
<div class="imageblock">
<div class="content">
<img src="../media/2025-02-07-zgc-vs-g1gc-for-scala/300-zgc.png" alt="300 ZGC" width="600">
</div>
</div>
</div>
<div class="sect3">
<h4 id="_600_messages_per_second_g1">600 messages per second G1</h4>
<div class="imageblock">
<div class="content">
<img src="../media/2025-02-07-zgc-vs-g1gc-for-scala/600-g1.png" alt="600 G1" width="600">
</div>
</div>
</div>
<div class="sect3">
<h4 id="_600_messages_per_second_zgc">600 messages per second ZGC</h4>
<div class="imageblock">
<div class="content">
<img src="../media/2025-02-07-zgc-vs-g1gc-for-scala/600-zgc.png" alt="600 ZGC" width="600">
</div>
</div>
</div>
<div class="sect3">
<h4 id="_900_messages_per_second_g1">900 messages per second G1</h4>
<div class="imageblock">
<div class="content">
<img src="../media/2025-02-07-zgc-vs-g1gc-for-scala/900-g1.png" alt="900 G1" width="600">
</div>
</div>
</div>
<div class="sect3">
<h4 id="_900_messages_per_second_zgc">900 messages per second ZGC</h4>
<div class="imageblock">
<div class="content">
<img src="../media/2025-02-07-zgc-vs-g1gc-for-scala/900-zgc.png" alt="900 ZGC" width="600">
</div>
</div>
<div class="ulist">
<ul>
<li>
<p>ZGC maintained ultra-low latency across all sample sizes.</p>
</li>
<li>
<p>G1GC delivered predictable pause times but showed increased latency under heavy load.</p>
</li>
<li>
<p>Generational ZGC improved short-lived object management, enhancing overall efficiency.</p>
</li>
</ul>
</div>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_conclusion">Conclusion</h2>
<div class="sectionbody">
<div class="paragraph">
<p>ZGC and G1GC both offer unique advantages for Scala applications:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>ZGC is the best choice for ultra-low latency and massive heap scalability.</p>
</li>
<li>
<p>G1GC is ideal for general-purpose applications requiring predictable performance tuning.</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>Ultimately, selecting the right GC strategy depends on workload characteristics and performance requirements. Benchmarking under real-world conditions remains the key to making an informed decision.</p>
</div>
<div class="paragraph">
<p>SCALA-LUJAH! Happy coding!</p>
</div>
</div>
</div>
<]]></content:encoded>
					
		
		
			</item>
         
	<item>
		<title>JVM vs JVM</title>
		<link>https://blog.lunatech.com//posts/2024-11-29-jvm-vs-jvm</link>
		
		<dc:creator><![CDATA[Nika Shamova]]></dc:creator>
        <pubDate>2024-11-29T00:00:00.000Z</pubDate>
         
             {
            <category><![CDATA[java]]></category>
                }
             {
            <category><![CDATA[jvm]]></category>
                }
             {
            <category><![CDATA[java-vs-world]]></category>
                }
             {
            <category><![CDATA[java-over-java]]></category>
                }
             {
            <category><![CDATA[en]]></category>
                }
             
        
		<guid isPermaLink="false">https://blog.lunatech.com//posts/2024-11-29-jvm-vs-jvm</guid>

					<description>
                        <![CDATA[ You’ve probably heard people talk about different JVMs, each claiming to be the best. It made me wonder: why are there so many? What makes one JVM better than another? In this article, we’ll try to break down what the JVM is, how it works, and why there are so many different implementations.]]></description>
                    <content:encoded><![CDATA[
                    <div class="sect1">
<h2 id="_introduction">Introduction</h2>
<div class="sectionbody">
<div class="paragraph">
<p>You’ve probably heard people talk about different JVMs, each claiming to be the best. It made me wonder: why are there so many? What makes one JVM better than another? In this article, we’ll try to break down what the JVM is, how it works, and why there are so many different implementations.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_basic_concepts">Basic Concepts</h2>
<div class="sectionbody">
<div class="sect2">
<h3 id="_java_abbreviation_overload_jdk_jre_jvm">Java Abbreviation Overload: JDK, JRE, JVM</h3>
<div class="paragraph">
<p>If you’re working with Java, you’ve likely encountered terms like JVM, JRE, and JDK. But what do they mean, and how are they connected? Let’s break it down:</p>
</div>
<div class="sect3">
<h4 id="_jdk_java_development_kit">JDK (Java Development Kit)</h4>
<div class="paragraph">
<p>This is a toolkit designed for Java developers. It includes everything you need to write and build Java applications:
- A compiler (<code>javac</code>) to turn Java source code into bytecode.
- Development libraries such as tools for debugging, monitoring, and packaging Java programs.
- The JRE (our next guest, see below).</p>
</div>
</div>
<div class="sect3">
<h4 id="_jre_java_runtime_environment">JRE (Java Runtime Environment)</h4>
<div class="paragraph">
<p>This is the software environment required to run Java applications:
- Runtime libraries: Core Java libraries (e.g., <code>java.lang</code>, <code>java.util</code>) and APIs for features like file I/O, networking, and concurrency.
- The JVM (another guest, which is described below), which executes the bytecode.</p>
</div>
</div>
<div class="sect3">
<h4 id="_jvm_java_virtual_machine">JVM (Java Virtual Machine)</h4>
<div class="paragraph">
<p>At the core of the Java runtime, it is responsible for:
- Loading and executing Java bytecode, a platform-independent instruction set generated when Java code is compiled.
- Optimizing performance with features like JIT (Just-In-Time) Compilation, which translates bytecode into machine-specific code during execution.</p>
</div>
</div>
</div>
<div class="sect2">
<h3 id="_java_bytecode">Java bytecode</h3>
<div class="paragraph">
<p>Bytecode is an intermediate, low-level language into which Java source code is compiled. It allows Java applications to run on any platform with a JVM, enabling the "write once, run anywhere" promise.</p>
</div>
</div>
<div class="sect2">
<h3 id="_jit_just_in_time_compilation">JIT (Just-In-Time) Compilation</h3>
<div class="paragraph">
<p>To improve speed, the JVM uses JIT to dynamically translate bytecode into native machine code at runtime. This reduces interpretation overhead, making applications faster.</p>
</div>
</div>
<div class="sect2">
<h3 id="_aot_ahead_of_time_compilation">AOT (Ahead-Of-Time) Compilation</h3>
<div class="paragraph">
<p>While JIT improves performance during execution, some environments benefit from Ahead-Of-Time (AOT) Compilation, which compiles bytecode into native code before runtime. This approach is often used in resource-constrained environments, where startup speed and memory efficiency are critical.</p>
</div>
</div>
<div class="sect2">
<h3 id="_how_do_they_fit_together">How Do They Fit Together?</h3>
<div class="ulist">
<ul>
<li>
<p>JDK: Developers use it to create Java applications.</p>
</li>
<li>
<p>JRE: Users rely on it to run Java applications.</p>
</li>
<li>
<p>JVM: This is the part of the JRE that runs Java bytecode.</p>
</li>
</ul>
</div>
<div class="imageblock">
<div class="content">
<img src="../media/2024-11-29-jvm-vs-jvm/jdk-jre-jvm.png" alt="JDK &lt; JRE &lt; JVM" width="200">
</div>
</div>
<div class="paragraph">
<p>During execution, the JVM can:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>Use the JIT compiler to boost performance by translating bytecode to machine code on the fly.</p>
</li>
<li>
<p>Optionally benefit from AOT compilation to further improve startup times and efficiency in specific scenarios.</p>
</li>
</ul>
</div>
<div class="sect3">
<h4 id="_tldr">TLDR</h4>
<div class="paragraph">
<p>The JDK includes the JRE, and the JRE contains the JVM. Together, they enable Java programs to be developed, executed, and optimized for a wide variety of platforms and use cases.</p>
</div>
</div>
</div>
<div class="sect2">
<h3 id="_write_once_run_anywhere">Write Once, Run Anywhere</h3>
<div class="paragraph">
<p>The JVM is an abstract computing machine that enables Java applications to run on any hardware or operating system. It translates platform-independent bytecode into machine-specific instructions, ensuring seamless compatibility across environments.</p>
</div>
<div class="paragraph">
<p>In simpler terms, JVM developers handle the heavy lifting. Their job is to build a robust, cross-platform JVM that works on all environments. This allows Java developers to focus on writing code without worrying too much about the specifics of different platforms. (Though, let’s be real—sometimes they still have to consider it, but that’s a story for another day.)</p>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_jvm_history">JVM History</h2>
<div class="sectionbody">
<div class="sect2">
<h3 id="_the_beginning_of_jvm">The Beginning of JVM</h3>
<div class="sect3">
<h4 id="_first_implementation_of_the_jvm">First Implementation of the JVM</h4>
<div class="paragraph">
<p>The first implementation of the JVM was part of JDK 1.0, released in January 1996. Sun Microsystems developed this initial JVM in C. It was bundled with the early versions of the Java Development Kit (JDK), which included tools such as <code>javac</code> (the Java compiler) and runtime libraries.</p>
</div>
</div>
<div class="sect3">
<h4 id="_other_early_implementations">Other Early Implementations</h4>
<div class="paragraph">
<p>After the initial Sun JVM, several other JVM implementations were developed:</p>
</div>
<div class="ulist">
<ul>
<li>
<p><strong>Kaffe</strong>: An independent, open-source implementation of the JVM. It aimed to provide a lightweight alternative to Sun&#8217;s JVM, which is well-suited for embedded systems.</p>
</li>
<li>
<p><strong>IBM J9 (later OpenJ9)</strong>: IBM&#8217;s implementation focused on enterprise environments, emphasizing performance and tuning capabilities.</p>
</li>
<li>
<p><strong>Oracle JRockit</strong>: A JVM optimized for server-side performance, especially in low-latency environments. Oracle acquired it and later merged features with the HotSpot JVM.</p>
</li>
<li>
<p><strong>HotSpot JVM</strong>: Originally developed by Longview Technologies, HotSpot was acquired by Sun Microsystems. It introduced Just-In-Time (JIT) compilation and adaptive optimization techniques. HotSpot eventually became the default JVM in the Java SE platform.</p>
</li>
</ul>
</div>
</div>
</div>
<div class="sect2">
<h3 id="_what_is_the_deal_with_openjdk_and_oracle_jdk">What is the Deal with OpenJDK and Oracle JDK?</h3>
<div class="paragraph">
<p>OpenJDK and Oracle JDK are closely related, especially since Java 11. OpenJDK is the open-source implementation of the Java SE Platform, while Oracle JDK is a commercial build based on OpenJDK. Both share the same codebase, meaning their functionality is nearly identical from Java 11 onward.</p>
</div>
<div class="ulist">
<ul>
<li>
<p><strong>Oracle JDK historically</strong>: included exclusive "commercial features" like Flight Recorder, Java Mission Control, and Application Class-Data Sharing. However, these features were added to OpenJDK starting with Java 11, eliminating most differences between the two.</p>
</li>
<li>
<p>The main distinction now lies in licensing and support. OpenJDK is free under the GNU General Public License (GPL), while Oracle JDK requires a commercial license for production use and comes with additional long-term support options for businesses. Essentially, OpenJDK is the foundation for Oracle JDK, and they are almost identical in technical terms for modern Java versions.</p>
</li>
</ul>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_jvm_vs_jvm">JVM vs JVM</h2>
<div class="sectionbody">
<div class="sect2">
<h3 id="_so_many_jvms_what_is_the_difference">So Many JVMs, What is the Difference?</h3>
<div class="paragraph">
<p>There are so many JDKs and JVMs available these days. Let’s explore a few of them to see how they differ and what unique features they offer!</p>
</div>
<div class="sect3">
<h4 id="_openjdk">OpenJDK</h4>
<div class="paragraph">
<p>The Open Java Development Kit (OpenJDK) is an open-source implementation of the Java Platform, Standard Edition (Java SE).</p>
</div>
<div class="ulist">
<ul>
<li>
<p><strong>Reference Implementation</strong>: OpenJDK is the official reference implementation of Java SE, ensuring compliance with the Java SE specifications. Many other distributions use it as a core.</p>
</li>
<li>
<p><strong>Regular Release Cycle</strong>: OpenJDK follows a six-month release cycle, with Long-Term Support (LTS) versions every three years.</p>
</li>
<li>
<p><strong>Community-Driven</strong>: Features like improved garbage collectors, API updates, and performance optimizations are developed as an open-source.</p>
</li>
<li>
<p><strong>Cross-Platform</strong>: OpenJDK supports major operating systems like Linux, macOS, and Windows, as well as architectures like x86, ARM, and RISC-V.</p>
</li>
<li>
<p><strong>Licensing</strong>: OpenJDK is distributed under a GPL license, allowing it to be used freely for all purposes, including commercial applications.</p>
</li>
</ul>
</div>
</div>
<div class="sect3">
<h4 id="_oracle_jdk">Oracle JDK</h4>
<div class="paragraph">
<p>The Oracle JDK is Oracle’s distribution of the Java Development Kit. It shares the same codebase as the open-source OpenJDK but comes with some proprietary features and licensing.</p>
</div>
<div class="ulist">
<ul>
<li>
<p>Oracle JDK is based on OpenJDK but includes additional optimizations and patches.</p>
</li>
<li>
<p>Oracle ensures backward compatibility and long-term support for enterprise users.</p>
</li>
<li>
<p>Access to critical bug fixes before they are included in publicly available releases.</p>
</li>
</ul>
</div>
</div>
<div class="sect3">
<h4 id="_graalvm">GraalVM</h4>
<div class="paragraph">
<p>GraalVM is a powerful version of the JDK that offers AOT native image compilation. It also enables  integration between multiple programming languages using the Truffle framework. With Truffle, programs written in different supported languages can work together easily. For instance, a JavaScript program can call Ruby methods and share data without duplicating it.</p>
</div>
<div class="ulist">
<ul>
<li>
<p>Compiler: GraalVM introduces the Graal JIT Compiler, a replacement for the traditional HotSpot C2 compiler.</p>
<div class="ulist">
<ul>
<li>
<p>Written in Java, the compiler is highly modular and easier to maintain and extend than older compilers written in C++.</p>
</li>
<li>
<p>Implements advanced optimizations like speculative optimizations, partial escape analysis, and inlining across multiple languages.</p>
</li>
</ul>
</div>
</li>
<li>
<p>Polyglot Support: GraalVM uses the Truffle language implementation framework, a platform for building interpreters for various languages. Each language runtime is implemented as a Truffle interpreter. Truffle is a framework for building language interpreters. When combined with the Graal compiler, these interpreters are automatically optimized with just-in-time (JIT) compilation, enabling programs running on them to achieve performance comparable to standard Java.</p>
</li>
<li>
<p>Native Image: Provides an AOT compilation feature called native image. Transforms JVM-based applications into standalone executables with reduced startup times and memory footprints.</p>
</li>
<li>
<p>Implementation Base: GraalVM builds on top of the OpenJDK HotSpot JVM. It replaces components like the compiler while retaining others, such as the garbage collector, class loader, and bytecode interpreter.</p>
</li>
</ul>
</div>
</div>
<div class="sect3">
<h4 id="_azul_jdk">Azul JDK</h4>
<div class="paragraph">
<p>Azul Systems provides two JDK distributions: Zulu and Zing.</p>
</div>
<div class="paragraph">
<p><strong>Zulu</strong>:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>A fully open-source JDK based on OpenJDK, claimed to be the world’s most secure and stable build of OpenJDK.</p>
</li>
<li>
<p>Delivers stabilized security builds.</p>
</li>
<li>
<p>Legacy Production Support for Java versions that are end of life by OpenJDK and Oracle including Java 6 &amp; 7 (but it has to be paid).</p>
</li>
</ul>
</div>
<div class="paragraph">
<p><strong>Zing (Azul Platform Prime)</strong>:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>A commercial JDK designed for extreme performance and low-latency requirements.</p>
</li>
<li>
<p>The Falcon JIT compiler enhances performance through advanced speculative optimizations. Built on LLVM, it executes Java code 20–50% faster.</p>
</li>
<li>
<p>ReadyNow! Technology: It allows the JVM to be restored from a snapshot of another JVM, enabling faster startup times and optimized performance.</p>
</li>
<li>
<p>The C4 Garbage Collector: A pauseless, generational GC. It eliminates most stop-the-world pauses, allowing applications to run smoothly during garbage collection.</p>
</li>
</ul>
</div>
</div>
</div>
<div class="sect2">
<h3 id="_use_cases">Use-Cases</h3>
<div class="paragraph">
<p>Choosing a JVM doesn’t have to be a grand philosophical debate—it really depends on what you need and how much effort or money you’re willing to invest. Let’s break it down.</p>
</div>
<div class="ulist">
<ul>
<li>
<p>If you’re just building something straightforward with a handful of users and don’t see the point of adding unnecessary complexity, go with <strong>OpenJDK</strong>. It’s free, dependable, and perfectly capable of handling your needs. Let’s face it, your 100 users won’t notice the difference, so why overthink it?</p>
</li>
<li>
<p>For the big, established enterprises out there, where your codebase is a mix of old systems (possibly older than some of your interns) and shiny new features, <strong>Oracle JDK</strong> might be worth considering. Sure, it comes with a price tag, but you’ll have dedicated support and the peace of mind that your massive, mission-critical applications are in good hands.</p>
</li>
<li>
<p>If you’re a fan of Java but like to keep your options open, dabbling in other languages or running cutting-edge setups with serverless architectures and microservices, <strong>GraalVM</strong> could be your match. The free Community Edition is great if you’re on a budget, but the Enterprise Edition offers powerful features if you’re ready to splurge a little for performance.</p>
</li>
<li>
<p>Not an Oracle fan? Don’t need fancy bells and whistles? Enter <strong>Zulu</strong>, the practical, no-nonsense choice for developers who just want a solid, affordable JVM alternative. It’s reliable, efficient, and does the job without any drama—perfect for those who like to keep things simple.</p>
</li>
<li>
<p>And for those working with massive, memory-hungry applications that demand peak performance, <strong>Zing</strong> is the way to go. It’s designed for situations where every ounce of garbage collection optimization matters. Yes, it’s a premium option, but when your application has to run fast and smooth, the investment can make all the difference.</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>And here you can see the algorithm, but don&#8217;t take it too seriously!</p>
</div>
<div class="imageblock">
<div class="content">
<img src="../media/2024-11-29-jvm-vs-jvm/jvm-vs-jvm.png" alt="How to choose the right JVM" width="400">
</div>
</div>
</div>
<div class="sect2">
<h3 id="_final_thoughts">Final Thoughts</h3>
<div class="paragraph">
<p>The JVM you choose should align with your project’s size, complexity, and budget. For small projects, OpenJDK or Zulu are often more than enough. For larger enterprises or performance-focused teams, investing in solutions like Oracle JDK, GraalVM, or Zing can pay off. Explore your options, and pick what works best for your needs!</p>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_conclusion">Conclusion</h2>
<div class="sectionbody">
<div class="paragraph">
<p>The JVM has evolved significantly since its debut with JDK 1.0, expanding from a single implementation to a diverse ecosystem of high-performance, specialized VMs. Building your own JVM or JDK requires deep knowledge of the Java specifications, low-level programming expertise, and a commitment to testing and optimization. If you&#8217;re genuinely considering this challenge, I must admit, I&#8217;m impressed! Best of luck! It&#8217;s a journey that will require immense dedication and effort!</p>
</div>
</div>
</div>
<]]></content:encoded>
					
		
		
			</item>
         
	<item>
		<title>AspectJ vs Spring AOP vs Quarkus: Aop Showdown</title>
		<link>https://blog.lunatech.com//posts/2024-11-22-aop-showdown</link>
		
		<dc:creator><![CDATA[Natan Tesfaye]]></dc:creator>
        <pubDate>2024-11-15T00:00:00.000Z</pubDate>
         
             {
            <category><![CDATA[java]]></category>
                }
             {
            <category><![CDATA[aop]]></category>
                }
             {
            <category><![CDATA[aspectj]]></category>
                }
             {
            <category><![CDATA[spring-aop]]></category>
                }
             {
            <category><![CDATA[java-vs-world]]></category>
                }
             {
            <category><![CDATA[java-over-java]]></category>
                }
             {
            <category><![CDATA[en]]></category>
                }
             
        
		<guid isPermaLink="false">https://blog.lunatech.com//posts/2024-11-22-aop-showdown</guid>

					<description>
                        <![CDATA[ Imaging you're developing a simple program, and you want to log every time a method is called. One option to do that is calling]]></description>
                    <content:encoded><![CDATA[
                    <div class="sect2">
<h3 id="_overview">Overview</h3>
<div class="paragraph">
<p>Imaging you&#8217;re developing a simple program, and you want to log every time a method is called. One option to do that is calling
the logger in every method.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">// Without AOP
public class UserService {
    public void createUser(String name) {
        System.out.println("Logging: createUser method called with name: " + name); // Logging logic
        System.out.println("User created: " + name);
    }
}

public class ProductService {
    public void addProduct(String product) {
        System.out.println("Logging: addProduct method called with product: " + product); // Logging logic
        System.out.println("Product added: " + product);
    }
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>But that is inefficient, and repetitive. Instead, We can use logging aspect  to handle all the logging when methods
are called.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;

@Aspect
public class LoggingAspect {

    // Pointcut: Matches all methods in UserService and ProductService classes
    @Pointcut("execution(* *Service.*(..))")
    public void userServiceMethods() {}

    // Logging logic before the method execution
    @Before("userServiceMethods()")
    public void logUserService() {
        System.out.println("Logging: createUser method called.");
    }

    @Before("productServiceMethods()")
    public void logProductService() {
        System.out.println("Logging: addProduct method called.");
    }
}

public class UserService {
    public void createUser(String name) {
        System.out.println("User created: " + name); // Core business logic
    }
}

public class ProductService {
    public void addProduct(String product) {
        System.out.println("Product added: " + product); // Core business logic
    }
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>When developing an application, you often encounter situations where certain functionality needs to be applied across various parts of the system—such as logging, error handling, or security. These are known as <strong>cross-cutting concerns</strong>, and traditionally, you&#8217;d end up repeating code across multiple classes or methods, leading to poor maintainability and scattered logic. This is where <strong>Aspect-Oriented Programming (AOP)</strong> comes in, allowing you to modularize these concerns separately from your business logic, making your code cleaner and easier to manage.</p>
</div>
<div class="paragraph">
<p>So, the purpose of Aspect-Oriented Programming (AOP) is to reduce code scattering and code tangling, improving the overall organization and maintainability of your code.</p>
</div>
<div class="paragraph">
<p><strong>Code Scattering</strong>: This occurs when the same functionality (like logging or security) is implemented repeatedly in multiple places across the codebase. AOP reduces scattering by centralizing such functionalities into modular components (aspects), so they only need to be defined once and can be applied wherever necessary.</p>
</div>
<div class="paragraph">
<p><strong>Code Tangling</strong>: This happens when multiple concerns (e.g., business logic, logging, error handling) are intertwined within the same code, making it difficult to understand or modify. AOP resolves this by separating concerns into distinct modules, allowing the business logic to remain clean and focused.
By addressing these issues, AOP enhances code modularity, making the codebase easier to manage, extend, and test.</p>
</div>
<div class="paragraph">
<p><strong>Key Concepts in AOP</strong></p>
</div>
<div class="paragraph">
<p><strong>Join Point</strong>: A point during the execution of a script.</p>
</div>
<div class="paragraph">
<p><strong>Pointcut</strong>: A regular expression that matches join points.</p>
</div>
<div class="paragraph">
<p><strong>Advice</strong>: Action Taken by an aspect at a join point.</p>
</div>
<div class="paragraph">
<p><strong>Aspect</strong>: A modularization of concerns that cuts across multiple objects.</p>
</div>
<div class="paragraph">
<p><strong>Weaving</strong>: process of integrating aspects (modularized cross-cutting concerns) into the main application code
at Join Points.</p>
</div>
</div>
<div class="sect2">
<h3 id="_aspectj">AspectJ</h3>
<div class="paragraph">
<p>AspectJ is an aspect-oriented extension to Java and one of the most robust implementations of AOP. It allows developers to modularize cross-cutting concerns and works seamlessly with any Java class. AspectJ supports compile-time, post-compile-time, and load-time weaving.</p>
</div>
<div class="paragraph">
<p>Example: Logging with AspectJ</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;

@Aspect
public class LoggingAspect {

    // Pointcut: Matches methods in classes under the package 'service'
    @Pointcut("execution(* service..*(..))")
    public void serviceMethods() {}

    // Logging logic applied before method execution
    @Before("serviceMethods()")
    public void logMethodExecution() {
        System.out.println("Logging: A service method was called.");
    }
}

public class UserService {
    public void createUser(String name) {
        System.out.println("User created: " + name); // Core business logic
    }
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>AspectJ offers flexibility with annotations or an XML-based configuration for managing aspects, making it highly versatile in various Java projects. AspectJ is framework-independent. It works directly with raw Java classes, making it suitable for standalone applications or projects not tied to any ecosystem.</p>
</div>
<div class="paragraph">
<p>AspectJ provides an extensive and fine-grained join point model, allowing developers to intercept and manipulate almost any point in a program&#8217;s execution. This includes Method executions, Constructor calls, etc.</p>
</div>
</div>
<div class="sect2">
<h3 id="_spring_aop">Spring AOP</h3>
<div class="paragraph">
<p>Spring AOP is a lightweight implementation of AOP, designed specifically for use with Spring&#8217;s IoC (Inversion of Control) container. It supports runtime weaving and is particularly well-suited for managing cross-cutting concerns in Spring-based applications.</p>
</div>
<div class="paragraph">
<p>Example: Logging with Spring AOP</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;

@Aspect
@Component
public class LoggingAspect {

    // Pointcut to match all methods in the service package
    @Pointcut("execution(* com.example.service..*(..))")
    public void serviceMethods() {}

    // Before advice to log method execution
    @Before("serviceMethods()")
    public void logBeforeMethod() {
        System.out.println("Logging: Service method invoked.");
    }
}

@Component
public class UserService {
    public void createUser(String name) {
        System.out.println("User created: " + name);
    }
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>Spring AOP integrates easily into Spring projects and relies on proxies for weaving, offering developers a clean and Spring-friendly approach to AOP.</p>
</div>
</div>
<div class="sect2">
<h3 id="_quarkus">Quarkus</h3>
<div class="paragraph">
<p>Quarkus, known for its Kubernetes-native Java stack, also supports AOP but in a simplified and efficient way compared to traditional implementations.</p>
</div>
<div class="paragraph">
<p>Example: Logging with Quarkus AOP</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">import io.quarkus.arc.Arc;
import javax.annotation.Priority;
import javax.interceptor.AroundInvoke;
import javax.interceptor.Interceptor;
import javax.interceptor.InvocationContext;

@Interceptor
@Priority(1)
@Logging
public class LoggingInterceptor {

    @AroundInvoke
    public Object logInvocation(InvocationContext context) throws Exception {
        System.out.println("Logging: Method called - " + context.getMethod().getName());
        return context.proceed();
    }
}

// Custom annotation to apply the interceptor
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.METHOD})
@InterceptorBinding
public @interface Logging {}

@Logging
public class UserService {
    public void createUser(String name) {
        System.out.println("User created: " + name);
    }
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>Quarkus brings AOP into the modern world of cloud-native, containerized Java applications. It uses <strong>build-time weaving</strong> to reduce the runtime overhead and optimize performance, which is crucial for microservices running in environments like Kubernetes. By leveraging <strong>CDI</strong> (Contexts and Dependency Injection), Quarkus simplifies the use of AOP, making it an excellent choice for developers building lightweight, fast, and highly performant Java applications in the cloud.</p>
</div>
</div>
<div class="sect2">
<h3 id="_final_note">Final Note</h3>
<div class="ulist">
<ul>
<li>
<p><strong>AspectJ</strong>: Best suited for complex, large-scale enterprise applications where flexibility and deep integration into the application’s lifecycle are required. The learning curve is steeper, and performance may be a consideration, but its capabilities in fine-grained join points and weaving techniques make it ideal for scenarios where AOP is deeply integrated into the system&#8217;s architecture.</p>
</li>
<li>
<p><strong>Spring AOP</strong>: Excellent for Spring-based applications where developers are looking for a lightweight, simple solution to apply cross-cutting concerns. It’s great for common needs such as logging and transaction management, but it’s limited to Spring-managed beans and doesn’t support all the advanced weaving options that AspectJ offers.</p>
</li>
<li>
<p><strong>Quarkus AOP</strong>: A perfect choice for cloud-native, containerized applications. If you’re building microservices or applications with performance-critical requirements, Quarkus is optimized for minimal runtime overhead and integrates well with modern development workflows like Kubernetes.</p>
</li>
</ul>
</div>
</div>
<div class="sect1">
<h2 id="_source">Source</h2>
<div class="sectionbody">
<div class="ulist">
<ul>
<li>
<p>[What is AOP? ](<a href="https://www.spiceworks.com/tech/devops/articles/what-is-aop/" class="bare">https://www.spiceworks.com/tech/devops/articles/what-is-aop/</a>)</p>
</li>
<li>
<p>[Spring AOP Documentation](<a href="https://docs.spring.io/spring-framework/reference/core/aop.html/" class="bare">https://docs.spring.io/spring-framework/reference/core/aop.html/</a>)</p>
</li>
<li>
<p>[AspectJ in Action - Manning](<a href="https://www.baeldung.com/aspectj" class="bare">https://www.baeldung.com/aspectj</a>)</p>
</li>
</ul>
</div>
</div>
</div>
<]]></content:encoded>
					
		
		
			</item>
         
	<item>
		<title>The Unit of a test</title>
		<link>https://blog.lunatech.com//posts/2024-11-15-the-unit-of-a-test</link>
		
		<dc:creator><![CDATA[Erik Bakker]]></dc:creator>
        <pubDate>2024-11-15T00:00:00.000Z</pubDate>
         
             {
            <category><![CDATA[java]]></category>
                }
             {
            <category><![CDATA[testing]]></category>
                }
             {
            <category><![CDATA[quality]]></category>
                }
             {
            <category><![CDATA[java-vs-world]]></category>
                }
             {
            <category><![CDATA[java-over-java]]></category>
                }
             {
            <category><![CDATA[en]]></category>
                }
             
        
		<guid isPermaLink="false">https://blog.lunatech.com//posts/2024-11-15-the-unit-of-a-test</guid>

					<description>
                        <![CDATA[ Have you ever heard someone about writing a test for a class or for a method? I bet you have. Yet this may be an indication of something being wrong. In this post, we'll discuss a common misconception about unit testing, what the impact of that misconception can be, and what to do instead.]]></description>
                    <content:encoded><![CDATA[
                    <div class="paragraph">
<p>Have you ever heard someone about writing a test for a class or for a method? I bet you have. Yet this may be an indication of something being wrong. In this post, we&#8217;ll discuss a common misconception about unit testing, what the impact of that misconception can be, and what to do instead.</p>
</div>
<div class="paragraph">
<p>The misconception is that the term <em>unit</em> in unit testing refers to a <em>structural unit</em>, such as a class or a method. But this should not be the intention. Instead, the intention should be to test a <em>unit of behaviour</em>.</p>
</div>
<div class="paragraph">
<p>Let&#8217;s look at an almost trivial example. Suppose we have a UserService that can retrieve users from a repository, but which has to map between two different domains. It would use following two classes:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">public class UserService {

	private final PeopleRepository peopleRepository;

	public UserService(PeopleRepository peopleRepository) {
		this.peopleRepository = peopleRepository;
	}

	public User getUserById(String id) {
		Person person = peopleRepository.getPersonById();
		return UserMapper.fromPerson(person);
	}

}

class UserMapper {
	static User fromPerson(Person person) {
		... map from person to user ...
	}
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>Now, a common mistake is that a proper unit test of the <code>UserService</code> requires to test it <em>in isolation from other classes</em>. In this case, that would mean to test the <code>UserService</code> without the real <code>UserMapper</code>, but instead with a test double for the <code>UserMapper</code>.</p>
</div>
<div class="paragraph">
<p>In this code, that&#8217;s hard, because there&#8217;s no way to make UserService use a test double. This may get people to modify the code to make replacement of the <code>UserMapper</code> possible:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">public class UserService {

	private final PeopleRepository peopleRepository;
	private final UserMapper userMapper;

	public UserService(PeopleRepository peopleRepository, UserMapper userMapper) {
		this.peopleRepository = peopleRepository;
		this.userMapper = userMapper;
	}

	public User getUserById(String id) {
		Person person = peopleRepository.getPersonById();
		return userMapper.fromPerson(person);
	}

}

public class UserMapper {
	User fromPerson(Person person) {
		... map from person to user ...
	}
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>We&#8217;ve changed the static invocation of <code>fromPerson</code> to a method call on an instance of <code>UserMapper</code>, which we added as a field and to the constructor of <code>PeopleService</code>.</p>
</div>
<div class="paragraph">
<p>Some people would exclaim: "See, this is why static methods are bad! They make testing hard!". Now, a test can be written:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">class UserServiceTest {

	@Mock
	UserMapper userMapper;

	@Mock
	PeopleRepository peopleRepository;

	@Test
	void testGetById() {
		UserService userService = new UserService(peopleRepository, userMapper);
		Person testPerson = new Person();
		when(peopleRepository.getPerson("123")).thenReturn(testPerson);
		User testUser = new User();
		when(userMapper.fromPerson(testPerson)).thenReturn(testUser);

		User user = userService.getUserById("123");

		assertEquals(testUser, user);
	}

}</code></pre>
</div>
</div>
<div class="paragraph">
<p>Now we managed to test this class 'in isolation', and some would say all is well. But all is not well, this is not a good unit test.</p>
</div>
<div class="paragraph">
<p>This test is now tied to specific implementation details, which makes it hard to maintain, and prone to requiring changes when the implementation (but not behaviour!) of the <code>UserService</code> changes. The whole existence of the <code>UserMapper</code> is an implementation detail, as is the method <code>fromPerson</code>. We should be able to refactor this whole class away, and for example create a private <code>mapPersonToUser</code> method right within the <code>UserService</code>. Such a refactoring should not require a change of the test.</p>
</div>
<div class="paragraph">
<p>(<a href="https://martinfowler.com/bliki/UnitTest.html)">Martin Fowler drew diagrams</a> similar to the ones below, that illustrate (<a href="https://leanpub.com/wewut)">Jay Fields</a>' concepts of Solitary and Sociable Unit tests:</p>
</div>
<div class="imageblock">
<div class="content">
<img src="../media/media/2024-11-15-the-unit-of-a-test/sociable-and-solitary-tests.png" alt="Diagram explaining sociable and solitary unit tests. Sociable tests test a structural unit including its collaborators. Solitary tests test a structural unit with collaborators replaced with test doubles." width="600">
</div>
</div>
<div class="paragraph">
<p>In our example, we could draw it with the following classes</p>
</div>
<div class="imageblock">
<div class="content">
<img src="../media/media/2024-11-15-the-unit-of-a-test/our-test-solitary.png" alt="Diagram showing how using the solitary testing style causes the test to be tied to implementation details such as the interface between UserService and UserMapper" width="400">
</div>
</div>
<div class="paragraph">
<p>Note that we took the solitary unit test approach here. The disadvantage is that now we&#8217;ve tied the test to the interface between the <code>UserService</code> class and it&#8217;s collaborator <code>UserMapper</code>.</p>
</div>
<div class="paragraph">
<p>If we would have made a sociable unit test instead, that would not have happened. We could have used the original code with the static method invocation of <code>UserMapper.fromPerson</code>, and our test would look like this:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">class UserServiceTest {

	@Mock
	PeopleRepository peopleRepository;

	@Test
	testGetById() {
		UserService userService = new UserService(peopleRepository);
		when(peopleRepository.getPerson("123")).thenReturn(testPerson);
		User user = userService.getUserById("123");
		assertEquals("123", user.id);
	}

}</code></pre>
</div>
</div>
<div class="paragraph">
<p>Our test is now simpler and no longer tied to the interface of <code>UserMapper</code>. As a diagram, it would now look like the following:</p>
</div>
<div class="imageblock">
<div class="content">
<img src="../media/media/2024-11-15-the-unit-of-a-test/our-test-sociable.png" alt="Diagram showing how our updated test uses the sociable style for the UserMapper collaborator, and which illustrates that the 'unit of behaviour' is implemented by the combination of the UserService and UserMapper" width="400">
</div>
</div>
<div class="paragraph">
<p>Here, we drew the dashed green line around both the <code>UserService</code> and the <code>UserMapper</code>, which together provide the <em>unit of behaviour</em> we&#8217;re trying to test.</p>
</div>
<div class="paragraph">
<p>Some final considerations. Maybe you <em>also</em> want to have tests for <code>UserMapper</code>, because it may have complex behaviour. That&#8217;s fine. There&#8217;s nothing wrong with the tests for the <code>UserService</code> using the real <code>UserMapper</code>, and there also being additional tests that provide better coverage of <code>UserMapper</code>.</p>
</div>
<div class="paragraph">
<p>In our code, we did use mocks for <code>UserRepository</code>, because we considered that a different unit of behaviour. Or maybe because it&#8217;s slow to test or modifies shared state. Unfortunately there are no hard rules for what exactly is a unit of behaviour, certainly not one that&#8217;s as easy as the structural unit counterpart of 'one class' or 'one method'. Picking a suitable unit of behaviour requires some taste. One thing you could take into consideration is whether a class really exposes a public interface (not in the technical sense of <code>public</code> or <code>interface</code>, but in the conceptual sense), that includes a clear contract and is relatively stable. If it does, replacing it with a test double may make sense. But classes that merely exist as an implementation detail are best tested in a sociable way.</p>
</div>
<]]></content:encoded>
					
		
		
			</item>
         
	<item>
		<title>Java 22 vs Java 23 and the Evolution of String Templates</title>
		<link>https://blog.lunatech.com//posts/2024-11-08-java-22-vs-java-23-and-the-evolution-of-string-templates</link>
		
		<dc:creator><![CDATA[Francesco Scala]]></dc:creator>
        <pubDate>2024-11-08T00:00:00.000Z</pubDate>
         
             {
            <category><![CDATA[java]]></category>
                }
             {
            <category><![CDATA[java-22]]></category>
                }
             {
            <category><![CDATA[java-23]]></category>
                }
             {
            <category><![CDATA[java-vs-world]]></category>
                }
             {
            <category><![CDATA[java-over-java]]></category>
                }
             {
            <category><![CDATA[en]]></category>
                }
             
        
		<guid isPermaLink="false">https://blog.lunatech.com//posts/2024-11-08-java-22-vs-java-23-and-the-evolution-of-string-templates</guid>

					<description>
                        <![CDATA[ With Java 22 and Java 23, our favorite JVM language got elevated to a higher level. Many features were included in these two releases, some of which are Pattern Matching for primitive types, Unnamed variables, and Markdown language support. Let's dive deeper into these features by looking at the bigger picture.]]></description>
                    <content:encoded><![CDATA[
                    <div id="preamble">
<div class="sectionbody">
<div class="paragraph">
<p>With Java 22 and Java 23, our favorite JVM language got elevated to a higher level. Many features were included in these two releases, some of which are Pattern Matching for primitive types, Unnamed variables, and Markdown language support. Let&#8217;s dive deeper into these features by looking at the bigger picture.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_pattern_matching">Pattern Matching</h2>
<div class="sectionbody">
<div class="sect2">
<h3 id="_jep_456_unnamed_variables">JEP 456: Unnamed Variables</h3>
<div class="paragraph">
<p>With JEP 456 from Java 22, developers can now make use of unnamed variables in their Java code. Simply put, unnamed variables are the variables required syntactically by the language but whose values don&#8217;t add anything to the code logic.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">String result = switch (expression) {
    case Integer _ -&gt; "Integer";
    case String _ -&gt; "String";
    default -&gt; "Unknown";
};</code></pre>
</div>
</div>
<div class="paragraph">
<p>Unnamed variables come in particularly handy when dealing with pattern matching in switch expressions, or inside try-catch blocks to define an exception that the developer won&#8217;t use.</p>
</div>
</div>
<div class="sect2">
<h3 id="_jep_455_pattern_matching_for_primitive_types">JEP 455: Pattern Matching for Primitive Types</h3>
<div class="paragraph">
<p>This preview feature of Java 23 enables pattern matching for primitive types. Thanks to it, developers can directly compare primitive types in pattern matching, without having to use their wrapper classes (Integer, Double, etc.).</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">int x = 55;
switch (x) {
    case 200 -&gt; System.out.println("OK");
    case 404 -&gt; System.out.println("Resource Not Found");
    case 500 -&gt; System.out.println("Internal Server Error");
    case int k -&gt; System.out.println("Unknown status: " + k);
}</code></pre>
</div>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_module_import_declarations_and_simplified_main_method">Module Import Declarations and Simplified Main Method</h2>
<div class="sectionbody">
<div class="sect2">
<h3 id="_jep_476_simplified_main_method">JEP 476: Simplified Main Method</h3>
<div class="paragraph">
<p>Reducing boilerplate code is one of the main focuses for Java 21, 22, and 23. Thanks to JEP 476, it&#8217;s now possible to import all of the packages exported by a module inside a Java file. The syntax resembles the one for importing packages:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">import module java.base;</code></pre>
</div>
</div>
<div class="paragraph">
<p>When multiple modules are imported, and a class is defined in more than one package, the developer can import the desired package to resolve the conflict:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">import module java.base;
import module java.desktop;

import java.util.List;</code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="_jep_463_simplified_main_method_declaration">JEP 463: Simplified Main Method Declaration</h3>
<div class="paragraph">
<p>With this feature, Java enables developers to implicitly declare classes around a main method. Beginners will now struggle less to write an executable Java file, and the more experienced developers will benefit from the reduced boilerplate code.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">void main() {
    System.out.println("Hello, World!");
}</code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="_jep_477_enhanced_main_method">JEP 477: Enhanced Main Method</h3>
<div class="paragraph">
<p>JEP 477 also contributes to the simplification of the main method. Implicitly declared classes now implicitly import the <code>java.base</code> module and <code>java.io.IO</code> package. This new package includes the methods:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">public static void print(Object obj);
public static void println(Object obj);
public static void readln(String prompt);</code></pre>
</div>
</div>
<div class="paragraph">
<p>Therefore, a simple Java file with a main method will now look like:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">void main() {
    String city = readln("Please enter a city: ");
    print("City: ");
    println(city);
}</code></pre>
</div>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_flexible_subclass_constructor">Flexible Subclass Constructor</h2>
<div class="sectionbody">
<div class="sect2">
<h3 id="_jep_447_flexible_superclass_constructors">JEP 447: Flexible Superclass Constructors</h3>
<div class="paragraph">
<p>As of before Java 22, subclass constructors should always include the call to the superclass constructor as the first statement. Any validation or initialization before the call to the superclass constructor would throw a compilation error.</p>
</div>
<div class="paragraph">
<p>JEP 447 is the first attempt of Java to change this constraint. Developers can now add logic in subclass constructors before the <code>super()</code> call. However, class fields cannot be initialized.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">public class SubClass extends SuperClass {

    public SubClass(List&lt;String&gt; data) {
        String element;
        if (data != null &amp;&amp; !data.isEmpty()) {
            element = data.get(0).toLowerCase();
        } else {
            element = "&lt;n/a&gt;";
        }

        super(element);
    }
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>Records can also benefit from this feature:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">public record Email(String local, String domain) {

    public Email(String fqda) {
        Objects.requireNonNull(fqda);
        var parts = fqda.split("@");
        if (parts.length != 2) {
            throw new IllegalArgumentException("Invalid email format");
        }

        this(parts[0], parts[1]);
    }
}</code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="_jep_482_enhanced_subclass_constructors">JEP 482: Enhanced Subclass Constructors</h3>
<div class="paragraph">
<p>JEP 482 extends the possibilities of JEP 447 by allowing developers to initialize class fields inside the subclass constructor before the superclass constructor call.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">class Super {

    Super() {
        overriddenMethod();
    }

    void overriddenMethod() {
        System.out.println("hello");
    }
}

class Sub extends Super {
    final int x;

    Sub(int x) {
        this.x = x;
        super();
    }

    @Override
    void overriddenMethod() {
        System.out.println(x);
    }
}</code></pre>
</div>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_string_templates_what_happened">String Templates&#8230;&#8203; What happened?</h2>
<div class="sectionbody">
<div class="paragraph">
<p>String Templates were supposed to be included in Java 23. However, that didn&#8217;t happen, and the only way to use those in Java is by switching back to Java 22 with Preview Features enabled. Let&#8217;s have a look at what String Templates are, the issues that were raised by the community, and what&#8217;s going to happen next.</p>
</div>
<div class="sect2">
<h3 id="_introduction">Introduction</h3>
<div class="paragraph">
<p>String Templates are Java&#8217;s solution to string interpolation. They couple literal text with embedded expressions and template processors to produce specialized results.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">String customerName = "Java Duke";
String phone = "555-123-4567";
String address = "1 Maple Drive, Anytown";
String json = STR."""
{
    "name": "\{customerName}",
    "phone": "\{phone}",
    "address": "\{address}"
}
""";</code></pre>
</div>
</div>
<div class="paragraph">
<p>In order to define a template, the developers need to specify the abstract processor they want to use. Java provides three of them: STR, FMT, and RAW.</p>
</div>
<div class="ulist">
<ul>
<li>
<p><strong>STR</strong>: Processes the template and returns a String.</p>
</li>
<li>
<p><strong>FMT</strong>: Processes the template, together with the formatting rules specified, and returns a String.</p>
</li>
<li>
<p><strong>RAW</strong>: Returns an instance of <code>StringTemplate</code>. Especially useful when creating a custom String Template Processor.</p>
</li>
</ul>
</div>
</div>
<div class="sect2">
<h3 id="_design_issues">Design Issues</h3>
<div class="paragraph">
<p>Several design issues were raised a few weeks before the Java 23 release:</p>
</div>
<div class="ulist">
<ul>
<li>
<p><strong>Coupling</strong>: Template capture and processing are now tightly coupled when the two things should be separated and composable.</p>
</li>
<li>
<p><strong>$ vs \{}</strong>: Some developers complained about the choice of the character for string interpolation. Some would have preferred the dollar sign, as it is used in other programming languages like JavaScript. However, this complaint felt more like syntactic sugar than an actual issue. Future versions of String Templates will most likely stick with \{}.</p>
</li>
<li>
<p><strong>Explicit processor abstraction</strong>: Java already has a way of abstracting the implementation of a behavior given a desired input and output: methods. The whole setting of the abstract processors to process String Templates felt unnecessary. Eventually, <code>String.format()</code> could be extended to accept a parameter with type <code>StringTemplate</code>, and produce the desired output.</p>
</li>
</ul>
</div>
</div>
<div class="sect2">
<h3 id="_future_of_string_templates">Future of String Templates</h3>
<div class="paragraph">
<p>As of today, there is no clear news on when String Templates will be back again.</p>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_other_cool_features">Other (cool) features</h2>
<div class="sectionbody">
<div class="paragraph">
<p>Java 22 and 23 bring several other exciting features to the table, enhancing the language&#8217;s capabilities and improving developer productivity. Some of them are listed below:</p>
</div>
<div class="ulist">
<ul>
<li>
<p><strong>JEP 467</strong>: JavaDoc using Markdown language.</p>
</li>
<li>
<p><strong>JEP 462</strong>: API for structured concurrency.</p>
</li>
<li>
<p><strong>JEP 464</strong>: Scoped Values.</p>
</li>
</ul>
</div>
</div>
</div>
<]]></content:encoded>
					
		
		
			</item>
         
	<item>
		<title>Maven vs Gradle Navigating the World of Java Build Tools</title>
		<link>https://blog.lunatech.com//posts/2024-11-01-maven-vs-gradle</link>
		
		<dc:creator><![CDATA[Giovanni Barbaro]]></dc:creator>
        <pubDate>2024-11-01T00:00:00.000Z</pubDate>
         
             {
            <category><![CDATA[java]]></category>
                }
             {
            <category><![CDATA[maven]]></category>
                }
             {
            <category><![CDATA[gradle]]></category>
                }
             {
            <category><![CDATA[java-vs-world]]></category>
                }
             {
            <category><![CDATA[java-over-java]]></category>
                }
             {
            <category><![CDATA[en]]></category>
                }
             
        
		<guid isPermaLink="false">https://blog.lunatech.com//posts/2024-11-01-maven-vs-gradle</guid>

					<description>
                        <![CDATA[ This is the first of a series of articles for Lunatech's *Java over Java* series. A seasonal occurrence]]></description>
                    <content:encoded><![CDATA[
                    <div id="preamble">
<div class="sectionbody">
<div class="paragraph">
<p>This is the first of a series of articles for Lunatech&#8217;s <strong>Java over Java</strong> series. A seasonal occurrence
where we pick a topic for a month and hold a series of presentations and articles about it. This season&#8217;s topic
will be <a href="https://blog.lunatech.com/tags/java-vs-world">"Java vs the world"</a>, follow the link to see other
articles from this series.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_introduction">Introduction</h2>
<div class="sectionbody">
<div class="paragraph">
<p>Building tools have become part of our daily life as software engineers. There is almost no project that doesn&#8217;t
make use of one, and there is no Java developer that hasn&#8217;t been exposed to Maven at least once.
With it being such a commonly used tool one would assume that every Java developer knows their building tool of choice
inside-out, but usually the exact opposite is true! (or at least it was for me!)</p>
</div>
<div class="paragraph">
<p>In today&#8217;s article we&#8217;ll take a look at the 2 most prominent building tools of recent years, Maven and Gradle,
and try to understand how both of them works, their differences and how to customize your build in each system!</p>
</div>
<div class="sidebarblock">
<div class="content">
<div class="paragraph">
<p>Disclaimer: We&#8217;ll be using Kotlin for our examples in Gradle</p>
</div>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_tools_overview">Tools overview</h2>
<div class="sectionbody">
<div class="paragraph">
<p>First of all, let&#8217;s take a quick look at both tools</p>
</div>
<table class="tableblock frame-all grid-all stretch">
<colgroup>
<col style="width: 33.3333%;">
<col style="width: 33.3333%;">
<col style="width: 33.3334%;">
</colgroup>
<thead>
<tr>
<th class="tableblock halign-left valign-top"></th>
<th class="tableblock halign-left valign-top">Maven</th>
<th class="tableblock halign-left valign-top">Gradle</th>
</tr>
</thead>
<tbody>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">Popularity</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Most popular Java building tool by far</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Popular in Android ecosystem and with Kotlin projects</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">Language</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">XML</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Groovy/Kotlin</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">Philosophy</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Convention over Configuration</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Configuration over Convention</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">Build Definition</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">All in one file (pom.xml)</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Defined in multiple files (settings, build, properties)</p></td>
</tr>
</tbody>
</table>
<div class="paragraph">
<p>Already at glance one can notice how different the two tools are. The most glaring difference is of course
the language used to describe the build process, but there is a lot more going on here that we&#8217;ll see today.</p>
</div>
<div class="paragraph">
<p>Going over the points one by one:</p>
</div>
<div class="ulist">
<ul>
<li>
<p><strong>Popularity:</strong> Maven is by far the most popular building tool for Java out there. This makes finding
guides, tools and online support much easier compared to the alternatives. With that said, Gradle is still quite
popular and its community is very dedicated, making all of these advantages less pronounced as they would otherwise be.</p>
</li>
<li>
<p><strong>Language:</strong> Most people are not huge fans of XML, so working with Maven&#8217;s build definitions isn&#8217;t everyone&#8217;s
favorite pastime and most would prefer used a full-fledged programming language as what happens in Gradle. While
IDEs do their best to improve Maven&#8217;s development experience, the reality is that it is way more structured, and XML
is part of the reason.</p>
</li>
<li>
<p><strong>Philosophy:</strong> The second reason that makes Maven way more "structured" comes down to the difference in
philosophy compared to Gradle.<br>
Maven is extremely opinionated and can be defined as "Convention over Configuration". There is usually
only one way to do something, and if you can&#8217;t find a plugin that satisfies your needs it can be
quite tricky to customize your build.<br>
Gradle on the other hand is extremely flexible, as one would expect from a building tool using a
programming language for its definitions.
It can be defined as "Configuration over Convention", as there are multiple ways to achieve the same goal
(there is a certain amount of convention, but it is not strongly enforced). This can sometimes lead to
confusion in beginners, as guides online tend to offer different approaches for the same problem.</p>
</li>
<li>
<p><strong>Build Definition:</strong> The Maven build definition happens entirely in its <code>pom.xml</code> file. This makes it
quite easy to work with.<br>
Gradle instead makes use of a variety of files, namely <code>build.gradle.kts</code>,<code>setting.gradle.kts</code> and <code>gradle.properties</code>.
This allows for greater "separation of concern", but adds some more complexity to it as well.</p>
</li>
</ul>
</div>
<div class="sect3">
<h4 id="_build_settings_properties">Build? Settings? Properties?</h4>
<div class="paragraph">
<p>As discussed in the previous chapter, there are quite a few files that can be used to define a gradle
build process. Here&#8217;s a quick overview for each one of them:</p>
</div>
<div class="ulist">
<ul>
<li>
<p><code>settings.gradle.kts</code>: Script that takes place before any build script. It is required when working
with multiple modules/projects, as it is responsible for setting up their hierarchy.</p>
</li>
<li>
<p><code>build.gradle.kts</code>: Describes the build for a single gradle project. It holds its dependencies, plugins and
available tasks</p>
</li>
<li>
<p><code>gradle.properties</code>: It&#8217;s a normal <code>.properties</code> file, its values can be easily used in the
<code>build.gradle.kts</code> script and, to a lesser extent, in the <code>setting.gradle.kts</code>. It is entirely optional.</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>To give a little example of the three files at work, we could have the current setup:</p>
</div>
<div class="paragraph">
<p>Our <code>gradle.properties</code></p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-properties" data-lang="properties">whoToGreet=Lunatech</code></pre>
</div>
</div>
<div class="paragraph">
<p>Bottom of <code>build.gradle.kts</code></p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-kotlin" data-lang="kotlin">val whoToGreet: String by project // Will get the value from the gradle.properties
println("Hello $whoToGreet from Build")</code></pre>
</div>
</div>
<div class="paragraph">
<p>Bottom of <code>settings.gradle.kts</code></p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-kotlin" data-lang="kotlin">val whoToGreet: String by settings // Will get the value from the gradle.properties
println("Hello $whoToGreet from Settings")</code></pre>
</div>
</div>
<div class="paragraph">
<p>When running <code>gradle tasks</code> you&#8217;ll see something like this:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-text" data-lang="text">Hello Lunatech from Settings

&gt; Configure project :
Hello Lunatech from Build

&gt; Task :tasks
...</code></pre>
</div>
</div>
<div class="paragraph">
<p>This shows us that the value <code>whoToGreet</code> was fetched by the <code>gradle.properties</code> file,
and that the <code>settings.gradle.kts</code> file was executed before the <code>gradle.build.kts</code> file.</p>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_tools_lifecycle">Tools Lifecycle</h2>
<div class="sectionbody">
<div class="paragraph">
<p>Besides syntactical differences, the two tools have very different approaches to their lifecycles as well.
Their documentation is very well-made, and as such we will make use of it in the following paragraphs where we try
to point out their differences.</p>
</div>
<div class="sect2">
<h3 id="_maven">Maven</h3>
<div class="paragraph">
<p>Maven has what I like to call a "fixed lifecycle". It has a predefined list of phases that have to be executed in order.
Here are the most popular phases, but there are quite a few more:</p>
</div>
<div class="olist arabic">
<ol class="arabic">
<li>
<p>validate</p>
</li>
<li>
<p>compile</p>
</li>
<li>
<p>test</p>
</li>
<li>
<p>package</p>
</li>
<li>
<p>verify</p>
</li>
<li>
<p>install</p>
</li>
<li>
<p>deploy</p>
</li>
</ol>
</div>
<div class="paragraph">
<p>When running a maven build you can target a specific phase, for example <code>mvn package</code> will target the
<code>package</code> phase. When a phase is targetted, all the phases before it will also be executed, so in our example
<code>validate</code>, <code>compile</code> and <code>test</code> would also be executed before <code>package</code>.</p>
</div>
<div class="paragraph">
<p>What happens in a specific phase is defined by <code>plugins</code>. A plugin in Maven is a piece of configuration
that allows to tie some script execution to a specific phase. Every time a <code>phase</code> is being processed
maven will check which plugins have mapped their executions to that specific <code>phase</code> and will execute them.</p>
</div>
<div class="imageblock">
<div class="content">
<img src="../media/2024-11-01-maven-vs-gradle/maven-lifecylce.png" alt="Maven lifecycle" width="600">
</div>
</div>
<div class="paragraph">
<p>To demonstrate this behaviour we can use an extremely simple plugin, <code>echo-maven-plugin</code>. This plugin
allows us to print any <code>message</code> we want during the build process.</p>
</div>
<div class="paragraph">
<p>We can add the following block to our <code>pom.xml</code></p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-xml" data-lang="xml">&lt;build&gt;
    &lt;!-- Maven Build Lifecycle --&gt;
    &lt;plugins&gt;
        &lt;plugin&gt;
            &lt;groupId&gt;com.github.ekryd.echo-maven-plugin&lt;/groupId&gt;
            &lt;artifactId&gt;echo-maven-plugin&lt;/artifactId&gt;
            &lt;version&gt;1.3.2&lt;/version&gt;
            &lt;executions&gt;
                &lt;execution&gt;
                    &lt;id&gt;echo-test&lt;/id&gt;
                    &lt;phase&gt;test&lt;/phase&gt;
                    &lt;goals&gt;
                        &lt;goal&gt;echo&lt;/goal&gt;
                    &lt;/goals&gt;
                    &lt;configuration&gt;
                        &lt;message&gt;Hello world at test&lt;/message&gt;
                    &lt;/configuration&gt;
                &lt;/execution&gt;
                &lt;execution&gt;
                    &lt;id&gt;echo-compile&lt;/id&gt;
                    &lt;phase&gt;compile&lt;/phase&gt;
                    &lt;goals&gt;
                        &lt;goal&gt;echo&lt;/goal&gt;
                    &lt;/goals&gt;
                    &lt;configuration&gt;
                        &lt;message&gt;Hello world at compile&lt;/message&gt;
                    &lt;/configuration&gt;
                &lt;/execution&gt;
                &lt;execution&gt;
                    &lt;id&gt;echo-validate&lt;/id&gt;
                    &lt;phase&gt;validate&lt;/phase&gt;
                    &lt;goals&gt;
                        &lt;goal&gt;echo&lt;/goal&gt;
                    &lt;/goals&gt;
                    &lt;configuration&gt;
                        &lt;message&gt;Hello world at validate&lt;/message&gt;
                    &lt;/configuration&gt;
                &lt;/execution&gt;
            &lt;/executions&gt;
        &lt;/plugin&gt;
    &lt;/plugins&gt;
&lt;/build&gt;</code></pre>
</div>
</div>
<div class="paragraph">
<p>For this plugin, we&#8217;re defining 3 different executions that will occur at 3 different phases: <code>validate</code>, <code>compile</code> and <code>test</code>.
Running <code>mvn test</code> should return something like this:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-text" data-lang="text">[INFO] --- echo:1.3.2:echo (echo-validate) @ maven_demo ---
[INFO] Hello world at validate
[INFO]
[INFO] --- resources:3.3.1:resources (default-resources) @ maven_demo ---
[INFO] Copying 0 resource from src/main/resources to target/classes
[INFO]
[INFO] --- compiler:3.13.0:compile (default-compile) @ maven_demo ---
[INFO] Recompiling the module because of changed source code.
[INFO] Compiling 2 source files with javac [debug target 17] to target/classes
[INFO]
[INFO] --- echo:1.3.2:echo (echo-compile) @ maven_demo ---
[INFO] Hello world at compile
[INFO]
[INFO] --- resources:3.3.1:testResources (default-testResources) @ maven_demo ---
[INFO] skip non existing resourceDirectory /Users/giovannibarbaro/Desktop/Personal/maven_gradle_demo/maven_demo/src/test/resources
[INFO]
[INFO] --- compiler:3.13.0:testCompile (default-testCompile) @ maven_demo ---
[INFO] Recompiling the module because of changed dependency.
[INFO]
[INFO] --- surefire:3.2.5:test (default-test) @ maven_demo ---
[INFO]
[INFO] --- echo:1.3.2:echo (echo-test) @ maven_demo ---
[INFO] Hello world at test</code></pre>
</div>
</div>
<div class="paragraph">
<p>We can see how the three plugin executions were processed not in the order that they were defined, but
in the lifecycle pre-determined order. It&#8217;s also possible to see how some default plugins will run even
if not defined in our <code>pom.xml</code>, as they&#8217;re pre-configured by maven itself.</p>
</div>
</div>
<div class="sect2">
<h3 id="_gradle">Gradle</h3>
<div class="paragraph">
<p>In Gradle, there is no strict "fixed lifecycle" as in Maven. Instead, Gradle relies on a task-based
model where tasks can be defined with custom actions and dependencies. Each task has a specific
purpose, and you can control the order and execution of tasks through dependencies or by explicitly
defining task relationships.</p>
</div>
<div class="imageblock">
<div class="content">
<img src="../media/2024-11-01-maven-vs-gradle/gradle-lifecycle.png" alt="Gradle Lifecycle" width="400">
</div>
</div>
<div class="paragraph">
<p>Gradle by default doesn&#8217;t come with any useful task, but thanks to the <code>Java</code> plugin a few key tasks are
added to our arsenal:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>assemble</p>
</li>
<li>
<p>build</p>
</li>
<li>
<p>check</p>
</li>
<li>
<p>clean</p>
</li>
<li>
<p>compileJava</p>
</li>
<li>
<p>test</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>When you run a Gradle build, you can specify a particular task, for example, <code>gradle build</code>. Gradle
will run all necessary dependent tasks, so in this example, compileJava, test, and assemble would
also execute as dependencies of build.</p>
</div>
<div class="paragraph">
<p>To experiment once again with this workflow, we can try to print some "Hellos". Let&#8217;s start by adding the
following script at the bottom of our <code>build.gradle.kts</code></p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-kotlin" data-lang="kotlin">val compileJava = tasks.named("compileJava")
val assemble = tasks.named("assemble")
val test = tasks.named("test")

val helloWorldCompile = tasks.register("helloCompile") {
    doFirst { println("Hello from compile") }
    dependsOn(compileJava)
}

tasks.register("helloAssemble") {
    doFirst { println("Hello from assemble") }
    dependsOn(assemble)
}

tasks.register("helloTest") {
    doFirst { println("Hello from test") }
    dependsOn(test)
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>Now we have registered 3 new tasks to our Gradle configuration: <code>helloCompile</code>, <code>helloAssemble</code>, <code>helloTest</code>
When executing any of these tasks, Gradle will first resolve their dependencies and then execute them.</p>
</div>
<div class="paragraph">
<p>As an example, this should be the output of <code>gradle helloAssemble --info</code></p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-text" data-lang="text">&gt; Task :compileJava UP-TO-DATE
:pluginDescriptors (Thread[Execution worker Thread 4,5,main]) started.

&gt; Task :pluginDescriptors
:processResources (Thread[Execution worker Thread 4,5,main]) started.

&gt; Task :processResources NO-SOURCE
:classes (Thread[Execution worker Thread 4,5,main]) started.

&gt; Task :classes UP-TO-DATE
:jar (Thread[Execution worker Thread 4,5,main]) started.

&gt; Task :jar
:assemble (Thread[Execution worker Thread 4,5,main]) started.

&gt; Task :assemble
:helloAssemble (Thread[Execution worker Thread 3,5,main]) started.

&gt; Task :helloAssemble
Hello from assemble</code></pre>
</div>
</div>
<div class="paragraph">
<p>We can see how <code>:assemble</code> and all of its dependencies had to be executed before <code>:helloAssemble</code> itself
is processed.</p>
</div>
<div class="paragraph">
<p>One important thing to note is that by defining the tasks as we did, they will only ever be processed when
called. If we want to define a task <code>A</code> that runs before/after another task <code>B</code> does, then we need change
task <code>B</code> as in the following example</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-kotlin" data-lang="kotlin">// :helloWorldCompile -&gt; task A
// :compileJava -&gt; task B
compileJava {
    // If you want for task A to run first
    dependsOn(helloWorldCompile)
    // If you want for task A to run last
    finalizedBy(helloWorldCompile)
}</code></pre>
</div>
</div>
<div class="sect3">
<h4 id="_gradle_plugin">Gradle plugin</h4>
<div class="paragraph">
<p>Gradle also has the concept of plugin. We won&#8217;t be exploring it too much in this article, but it is important
to know that it differs quite substantially from Maven&#8217;s plugin.</p>
</div>
<div class="paragraph">
<p>A Gradle plugin is highly flexible and allows dynamic changes in the build file. It adds tasks,
configurations, or custom logic directly to the build.gradle file, which can modify the build&#8217;s
behavior at different stages.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">// Not functional code, only here to show general structure
abstract public class GradlePluginExample implements Plugin&lt;Project&gt; {

    @Override
    public void apply(Project project) {
        project.getPlugin().apply(JavaPlugin.class);
        project.getDependencies().add("implementation", "plugin:lunatech:1.9.93");

        var helloWorld = project.getTasks().register("helloWorld", (task) -&gt; {
            System.out.println("Hello World!");
        });

        var compileJava = project.getTasks().getByName("compileJava");
        compileJava.finalizedBy(helloWorld);
    }
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>We can see how from the plugin&#8217;s <code>apply</code> method we can configure everything we could normally
access from the <code>build.gradle.kts</code>. So, while we could limit ourselves to just define a set of tasks
(which would make it similar to a Maven plugin), it has the full capabilities that are normally reserved
to a build file.</p>
</div>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_customizing_the_build_cycle">Customizing the build cycle</h2>
<div class="sectionbody">
<div class="paragraph">
<p>As we&#8217;ve seen, customizing the build lifecycle can easily be done with both tools. But while Gradle
tasks allow for custom code to be executed at any point of the build pipeline, maven relies on pre-packaged
scripts in the form of plugins that will then be executed at specific phases.</p>
</div>
<div class="sect2">
<h3 id="_scenario">Scenario</h3>
<div class="paragraph">
<p>We have a very small Java application at <code>app.Test</code> that reads a file from its <code>resources</code> and prints
it out. It looks something like this:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">public class Test {
    public static void main(String[] args) {
        System.out.println("Hello world");

        var inputStream = Test.class.getResourceAsStream("/java_vs_java.txt");
        var bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
        var result = bufferedReader.lines().collect(Collectors.joining("\n"));
        System.out.println(result);
    }
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>The kicker is, the file <code>java_vs_java.txt</code> does <em>not</em> exist, and we want to generate it during the build
lifecycle.</p>
</div>
</div>
<div class="sect2">
<h3 id="_maven_2">Maven</h3>
<div class="paragraph">
<p>Which options do we have if we&#8217;re working with Maven, and we can&#8217;t find the plugin that satisfies our needs?</p>
</div>
<div class="paragraph">
<p>There are 2 routes that we con follow in this scenario:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>Create our own plugin</p>
</li>
<li>
<p>Leverage <code>exec-maven-plugin</code>, <a href="https://www.mojohaus.org/exec-maven-plugin/index.html">a plugin</a> that allows to run custom code during the build lifecycle</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>Today we&#8217;ll explore the second option as it is the one that requires the least setup</p>
</div>
<div class="paragraph">
<p>The <code>exec-maven-plugin</code> plugin can run either Java classes or external programs. We&#8217;ll use it with
a Java class defined in our project to further minimize the needed setup.</p>
</div>
<div class="paragraph">
<p>We can create a simple Java application at <code>build.GenerateFile</code> that will take care of generating
the file that we need:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">public class GenerateFile {

    public static void main(String[] args) throws IOException {
        String destFile = args[0];
        String content = args[1];

        System.out.println("Creating file " + destFile);
        System.out.println("Content is " + content);

        var file = new File(destFile);
        file.getParentFile().mkdirs();
        file.createNewFile();

        var fileWriter = new FileWriter(file);
        fileWriter.write(content);
        fileWriter.close();
        System.out.println("File created: " + file.getAbsolutePath());
    }
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>Since we want to make this application reusable, we parametrized the destination file and its content.
Now that we&#8217;ve defined the application, we can call it as follows in our <code>pom.xml</code></p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-xml" data-lang="xml">&lt;build&gt;
    &lt;plugins&gt;
        &lt;plugin&gt;
            &lt;groupId&gt;org.codehaus.mojo&lt;/groupId&gt;
            &lt;artifactId&gt;exec-maven-plugin&lt;/artifactId&gt;
            &lt;version&gt;3.4.1&lt;/version&gt;
            &lt;executions&gt;
                &lt;execution&gt;
                    &lt;id&gt;generate-custom-resource&lt;/id&gt;
                    &lt;phase&gt;compile&lt;/phase&gt;
                    &lt;goals&gt;
                        &lt;goal&gt;java&lt;/goal&gt;
                    &lt;/goals&gt;
                    &lt;configuration&gt;
                        &lt;mainClass&gt;build.GenerateFile&lt;/mainClass&gt;
                        &lt;arguments&gt;
                            &lt;argument&gt;
                                ${project.build.outputDirectory}/java_vs_java.txt
                            &lt;/argument&gt;
                            &lt;argument&gt;Maven was able to create me!!&lt;/argument&gt;
                        &lt;/arguments&gt;
                    &lt;/configuration&gt;
                &lt;/execution&gt;
            &lt;/executions&gt;
        &lt;/plugin&gt;
    &lt;/plugins&gt;
&lt;/build&gt;</code></pre>
</div>
</div>
<div class="paragraph">
<p>Let&#8217;s take a closer look at some of the configurations here:</p>
</div>
<div class="ulist">
<ul>
<li>
<p><code>phase=compile</code>: This means that the code will run during the <code>compile</code> phase of the fixed lifecycle</p>
</li>
<li>
<p><code>goal=java</code>: This will specify that we&#8217;re running a Java application - <a href="https://www.mojohaus.org/exec-maven-plugin/java-mojo.html">More info here</a></p>
</li>
<li>
<p><code>mainClass=build.GenerateFile</code>: This points the plugin to the application that we want to run</p>
</li>
<li>
<p><code>arguments</code>: Here we pass the destination file and its content</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>Lastly, to see if the application is working, let&#8217;s run <code>java -cp ./target/maven_demo-1.0-SNAPSHOT.jar app.Test</code>.
We should see this:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-text" data-lang="text">Hello world
Maven was able to create me!!</code></pre>
</div>
</div>
<div class="paragraph">
<p>One thing that is important to notice is that we ran the application after the <code>compile</code> phase.
If we tried to use an earlier phase like <code>validate</code> we would have been met with a <code>java.lang.ClassNotFoundException: build.GenerateFile</code>.<br>
This happens because the <code>GenerateFile</code> itself hasn&#8217;t been compiled yet, so the <code>maven-exec-plugin</code>
won&#8217;t be able to execute it.</p>
</div>
<div class="paragraph">
<p>If you need to execute an application before the <code>compile</code> phase, consider moving the <code>GenerateFile</code>
application to another module or, at that point, consider investing the time to create a custom plugin.</p>
</div>
</div>
<div class="sect2">
<h3 id="_gradle_2">Gradle</h3>
<div class="paragraph">
<p>Since gradle is intrinsically more configurable, creating custom executions is more straight forward.
Given the same <code>app.Test</code>, we can achieve the file generation by adding this to our <code>build.gradle.kts</code>:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-kotlin" data-lang="kotlin">val generateFile = tasks.register("generateFile") {
    doFirst{
        val file = layout.buildDirectory.file("resources/main/java_vs_java.txt").get().asFile
        val content = "Gradle was able to create me!!"

        file.parentFile.mkdirs()
        file.createNewFile()
        file.writeText(content)
    }
}

assemble {
    dependsOn(generateFile)
}</code></pre>
</div>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_conclusion">Conclusion</h2>
<div class="sectionbody">
<div class="paragraph">
<p>Today we took a deep dive into Maven&#8217;s and Gradle&#8217;s build lifecycles, how they differ and how to leverage
both to achieve your ideal build pipeline.<br>
There is a lot of room to go even deeper into these topics,
like understanding how to better use the multi-module/project capabilities of both tools or how to create
custom plugins, but that will be the topic for another article!</p>
</div>
</div>
</div>
<]]></content:encoded>
					
		
		
			</item>
         
	<item>
		<title>Why the Women Automotive Network Summit Should Be on Your Radar: Diversity, Inclusion and Networking</title>
		<link>https://blog.lunatech.com//posts/2024-10-18-women-automotive</link>
		
		<dc:creator><![CDATA[]]></dc:creator>
        <pubDate>2024-10-18T00:00:00.000Z</pubDate>
         
             {
            <category><![CDATA[eclipse foundation]]></category>
                }
             {
            <category><![CDATA[automotive industry]]></category>
                }
             {
            <category><![CDATA[networking]]></category>
                }
             {
            <category><![CDATA[conference]]></category>
                }
             {
            <category><![CDATA[en]]></category>
                }
             
        
		<guid isPermaLink="false">https://blog.lunatech.com//posts/2024-10-18-women-automotive</guid>

					<description>
                        <![CDATA[ image::nika-kata.jpg[Photo of Veronika and Kateryna, 600]]]></description>
                    <content:encoded><![CDATA[
                    <div id="preamble">
<div class="sectionbody">
<div class="paragraph">
<p><strong>The Women Automotive Network (WAN) Summit Europe</strong> kicked off on October 8, 2024, in Stuttgart, Germany, focusing on the importance of diversity and inclusion in the automotive industry. Veronika Shamova and I, Kateryna Olenkovska, proudly represented Lunatech’s automotive expertise at the summit 😄 Veronika is a Site Reliability Engineer, and I am a Quality Assurance Specialist. Together, we are working with CARIAD to develop a Software Labeling Stack for creating and processing ground truth data. This summit was a great opportunity to connect business and software, reminding us that teamwork is just as important as coding.</p>
</div>
<div class="imageblock">
<div class="content">
<img src="../media/2024-10-18-women-automotive/nika-kata.jpg" alt="Photo of Veronika and Kateryna" width="600">
</div>
</div>
</div>
</div>
<div class="sect2">
<h3 id="_lets_take_a_closer_look_at_the_summits_purpose">Let’s take a closer look at the summit&#8217;s purpose</h3>
<div class="paragraph">
<p>The summit aimed to unite leading women in the automotive sector from companies like Porsche, Volkswagen, Volvo, and Jaguar, and more. The big goal is to build a strong network and share experiences that helped these women succeed. The WAN community has grown to 40,000 members worldwide and is continuing to expand.</p>
</div>
<div class="paragraph">
<p>A key focus of the summit is mentorship, which is essential for career growth. Members can choose to be mentors or mentees, helping each other navigate their professional journeys.</p>
</div>
</div>
<div class="sect2">
<h3 id="_so_what_happened_at_the_conference">So, what happened at the conference?</h3>
<div class="paragraph">
<p>In the morning, we were welcomed at the Forum am Schlosspark in Ludwigsburg, a lovely venue that accommodated all 500 attendees. An additional 500 participants joined the summit online. After registering and enjoying some coffee, we were invited into a spacious conference hall filled with round tables.</p>
</div>
<div class="imageblock">
<div class="content">
<img src="../media/2024-10-18-women-automotive/main-hall.jpg" alt="Photo of the main hall" width="600">
</div>
</div>
<div class="paragraph">
<p>The event began with a welcome speech from <strong>Micha Goebig</strong>, CEO and Founder of Go Big Coaching and Communication LLC. She shared insights about the community and stressed the importance of networking. "Don’t be shy to say hello to the woman next to you!" Micha encouraged us. With that, the summit officially began!</p>
</div>
<div class="imageblock">
<div class="content">
<img src="../media/2024-10-18-women-automotive/micha-goebig.jpg" alt="Welcome speech from Micha Goebig" width="600">
</div>
</div>
</div>
<div class="sect2">
<h3 id="_lets_look_at_some_highlights_from_the_talks">Let’s look at some highlights from the talks</h3>
<div class="paragraph">
<p>From <strong>Linda Jackson</strong>, CEO of Peugeot, we gained firsthand insight into what it takes to climb the corporate ladder. With 45 years of experience in the automotive industry, Linda emphasized the importance of confidence, perseverance, learning from mistakes, and growing alongside a trusted team. She also reminded us that on this long journey to the top, it’s crucial to pause and appreciate the view.</p>
</div>
<div class="imageblock">
<div class="content">
<img src="../media/2024-10-18-women-automotive/linda-jackson.jpg" alt="Talk from Linda Jackson" width="600">
</div>
</div>
<div class="paragraph">
<p><strong>Barbara Frenkel</strong>, Member of the Executive Board for Procurement at Porsche AG, delivered an inspiring talk titled “Follow Your Dream – My Path to the Porsche Executive Board.” The key takeaways from her presentation were to work hard, trust the process, and let your colleagues be your references. And who knows? One day, you might get a call from Porsche and be invited to become one of the nine board members!</p>
</div>
<div class="imageblock">
<div class="content">
<img src="../media/2024-10-18-women-automotive/barbara-frenkel.jpg" alt="Talk from Barbara Frenkel" width="600">
</div>
</div>
<div class="paragraph">
<p><strong>FLEX</strong> panel group initiated a discussion on how we make our business decisions. It turns out that these choices are rarely based solely on facts; instead, they often involve a mix of intuition and facts. It&#8217;s essential to trust your gut feeling and be willing to take risks to explore uncharted territories.</p>
</div>
<div class="paragraph">
<p>After lunch, we were ready to dive into new topics. This time, it was a workshop led by <strong>Sara Gallian</strong>, a SDV Program Manager at the Eclipse Foundation, which Lunatech is part of. This foundation creates a business-friendly environment for open-source software collaboration and innovation.</p>
</div>
<div class="imageblock">
<div class="content">
<img src="../media/2024-10-18-women-automotive/flex-sara.jpg" alt="Workshop led by Sara Gallian" width="600">
</div>
</div>
<div class="paragraph">
<p>The workshop, titled “Open Source for All: Democratising and Transforming the Automotive Software Industry in a Code-First Way,” highlighted the challenges open-source contributors face. These challenges include language barriers, cultural differences, years of experience and even unreliable internet connections.</p>
</div>
<div class="paragraph">
<p>We looked at charts showing cultural differences across countries, prompting us to think about our own experiences.</p>
</div>
<div class="imageblock">
<div class="content">
<img src="../media/2024-10-18-women-automotive/charts.jpg" alt="Charts showing cultural differences across countries" width="600">
</div>
</div>
<div class="paragraph">
<p>So, how can we enhance diversity in open source? We need to be more mindful and inclusive, making sure open source is a welcoming space for everyone, especially underrepresented groups. A typical open-source contributor can be anyone – it’s not just limited to a white, straight, cisgender man in his 40s! 😄</p>
</div>
<div class="paragraph">
<p>During the panel discussion, we learned that the industry is evolving, with women’s presence steadily growing and strong allies supporting diversity and inclusion at every turn. Looking ahead, there’s even more growth planned, with a goal to increase the representation of women in leadership positions from 20% to 25% by 2030. This goal is set to be achieved by enhancing mentorship and sponsorship networks within the industry, and WAN serves exactly that purpose.</p>
</div>
</div>
<div class="sect2">
<h3 id="_conclusion">Conclusion</h3>
<div class="paragraph">
<p>After a day packed with insights, we wrapped it up with a fun after-party, where networking flowed just as smoothly as the Aperol Spritz! While networking can be tough and sometimes intimidating, it’s definitely rewarding when you find those genuine connections that help you grow personally and professionally. We left feeling energized, with several connections in LinkedIn and excited for what’s to come.</p>
</div>
<div class="paragraph">
<p>All in all, as for someone with a software engineering background, this summit was a unique experience, it was different from typical software conferences. Instead of focusing on technical skills, it emphasized sharing career stories, taking on new challenges, and never giving up. Seeing so many successful women in the automotive industry was inspiring. The focus on building a strong community made the event even better. I enjoyed the talks and gained valuable insights and I’m looking forward to coming back next year!</p>
</div>
<div class="imageblock">
<div class="content">
<img src="../media/2024-10-18-women-automotive/end.jpg" alt="End of the event" width="600">
</div>
</div>
</div>
<div class="sect2">
<h3 id="_links">Links</h3>
<div class="paragraph">
<p>If you&#8217;re interested in learning more and want to experience a bit of the conference atmosphere, check out the recorded talks through this <a href="https://www.youtube.com/playlist?list=PLBvCIWq03PgrNYd_ASN_LWvJ8oq12Ub_-">link</a>!</p>
</div>
<div class="paragraph">
<p>Also, you can learn more about <a href="https://womenautomotivenetwork.com/en-eu">Women Automotive Network</a> and <a href="https://www.eclipse.org/">Eclipse Foundation</a> here.</p>
</div>
</div>
<]]></content:encoded>
					
		
		
			</item>
        
	</channel>
</rss>


