<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
<title>Roelof Jan Elsinga</title>
              <link href="https://roelofjanelsinga.nl"/>
              <updated>2026-09-30T13:40:20+02:00</updated>
              <author>
                <name>Roelof Jan Elsinga</name>
              </author>
              <id>https://roelofjanelsinga.nl</id>
              <link rel="self" href='https://roelofjanelsinga.nl/feed'/>
<entry>
                    <title><![CDATA[Waarom het moderniseren van je legacy PHP-systeem een slimme investering is voor groeiende MKB’s]]></title>
                    <link href="https://roelofjanelsinga.nl/articles/moderniseer-php-mkb/"/>
                    <id>https://roelofjanelsinga.nl/articles/moderniseer-php-mkb/</id>
                    <updated>2025-08-01T08:43:00+02:00</updated>
                    <published>2025-08-01T12:00:00+02:00</published>
                    <content type="html"><![CDATA[<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
<html><body><h1>Waarom het moderniseren van je legacy PHP-systeem een slimme investering is voor groeiende MKB&rsquo;s</h1>
<p><img src="https://aloia-systems.gumlet.io/images/articles/modernizing-php-applications.png?w=640&amp;h=426&amp;s=601f9df38597b876bb08b8734c3e2f5e" alt="Moderniseren van PHP-applicaties" loading="lazy" class="visibility-auto" title="Moderniseren van PHP-applicaties" srcset="https://aloia-systems.gumlet.io/images/articles/modernizing-php-applications.png?w=320&amp;h=213&amp;mode=crop&amp;crop=smart&amp;s=9717cc4cab43c8a19d2f1f213813907a 320w,https://aloia-systems.gumlet.io/images/articles/modernizing-php-applications.png?w=480&amp;h=319&amp;mode=crop&amp;crop=smart&amp;s=1cd2eeda2e829fbce0cddbd4ec1e69f7 480w,https://aloia-systems.gumlet.io/images/articles/modernizing-php-applications.png?w=640&amp;h=426&amp;mode=crop&amp;crop=smart&amp;s=fd72742319b2dc1827d1ec3f6fd6e836 640w" sizes="(max-width: 360px) 320px, max-width: 640px) 480px, 640px"></p>
<p>Voor de meeste kleine en middelgrote bedrijven is verouderde software een bekend probleem. Misschien begon het ooit als een simpel hulpmiddel dat prima werkte, maar inmiddels voelt het alsof je constant pleisters plakt om alles draaiende te houden. Je bent niet de enige. Veel MKB&rsquo;s besteden elke maand &euro;1.000 tot &euro;1.500 aan personeelsuren puur om tijdelijke oplossingen te gebruiken&mdash;zoals handmatig data overzetten, kleine foutjes herstellen en omgaan met onvoorspelbare kuren.</p>
<p>Maar het gaat niet alleen om verloren uren:</p>
<ul>
<li>Verouderde PHP-versies brengen beveiligingsrisico&rsquo;s met zich mee die klantgegevens &eacute;n je reputatie in gevaar brengen.</li>
<li>Prestatieproblemen vertragen je team en zorgen voor frustratie bij klanten.</li>
<li>Veranderingsangst maakt het duur en risicovol om nieuwe functies of verkoopkanalen toe te voegen.</li>
</ul>
<h2>Wat levert het moderniseren van je PHP-applicatie op?</h2>
<p>Een van de grootste frustraties bij ontwikkeling is een systeem dat strak in elkaar verweven zit, waardoor een kleine wijziging meerdere onderdelen breekt. Door te moderniseren breek je deze processen op en geef je je developmentteam de ruimte om weer te bouwen.</p>
<h3>1. Sterkere beveiliging = Continu&iuml;teit van je bedrijf</h3>
<p>Moderne PHP-frameworks dichten kwetsbaarheden nog v&oacute;&oacute;r hackers ze kunnen misbruiken. Zo bescherm je het vertrouwen van klanten, voorkom je dure downtime en blijf je voldoen aan regelgeving. Als je systeem al langer dan een jaar geen update heeft gehad, is de kans groot dat het kwetsbaar is.</p>
<h3>2. Snellere systemen = Tevreden klanten en medewerkers</h3>
<p>Met reactietijden onder de 300ms werkt je team sneller en genieten klanten van een soepele ervaring. Geen wachttijden meer voor dashboards of het verwerken van bestellingen tijdens piekmomenten.</p>
<h3>3. Minder onderhoud = Voorspelbare kosten</h3>
<p>Moderne code is makkelijker (en goedkoper) te onderhouden. Geen "spaghetti-code" meer waarbij een kleine wijziging drie andere dingen breekt. Onderhoud wordt routine in plaats van crisis.</p>
<p>Misschien een gewaagde uitspraak, maar het is prima om code te dupliceren als dat je systeem begrijpelijker en onderhoudsvriendelijker maakt. Liever duplicatie dan onbetrouwbaarheid.</p>
<h3>4. Klaar voor groei</h3>
<p>Wil je een nieuw verkoopkanaal toevoegen of rapportages automatiseren? Met een moderne basis kun je snel inspelen op nieuwe kansen. Geen volledige herbouw of maandenlange verstoring nodig.</p>
<h2>Wat kost het, en wat levert het op?</h2>
<p>Typische moderniseringsprojecten voor MKB&rsquo;s kosten tussen de &euro;5.000&ndash;&euro;25.000 en duren 3&ndash;6 maanden. Dit is een gemiddelde en hangt af van hoe groot je systeem is, hoeveel je wilt moderniseren, en eerlijk gezegd: wat jij het belangrijkst vindt. Moderniseren hoeft niet in &eacute;&eacute;n keer; je kunt prima klein beginnen en stapsgewijs uitbreiden.</p>
<p>De opbrengsten zijn echter duidelijk:</p>
<ul>
<li>Bespaar minimaal &euro;1.000&ndash;&euro;1.500 per maand aan personeelskosten (handmatig werk, fouten herstellen, gegevens achterhalen)</li>
<li>Minder spoedhulp en nachtelijke &ldquo;kun je dit NU fixen?&rdquo;-telefoontjes</li>
<li>Nieuwe inkomstenstromen sneller activeren (e-commerce, B2B-portalen, integraties)</li>
<li>Betere klanttevredenheid dankzij snellere en soepelere service</li>
</ul>
<p>De meeste bedrijven verdienen hun investering binnen 12&ndash;18 maanden volledig terug.</p>
<h2>Hoe moderniseren we zonder je bedrijf te verstoren?</h2>
<p>Moderniseren betekent niet opnieuw beginnen of wekenlang offline zijn.</p>
<p>Mijn aanpak is stapsgewijs, omdat jouw systeem gewoon operationeel moet blijven tijdens het proces. Dit zijn mijn stappen:</p>
<ol>
<li>Stabiliseren van wat het belangrijkst is, zoals klantdata en kernprocessen</li>
<li>Updaten van externe systeemintegraties</li>
<li>Nieuwe functies toevoegen (rapportages, automatisering, kanaalkoppelingen)</li>
</ol>
<p>Je merkt al snel verbeteringen, met minimale onderbreking en heldere communicatie in elke fase.</p>
<p>Nieuwe functies komen bewust als laatste stap, zodat ik het project op tijd &eacute;n binnen budget kan afronden. Te vroeg beginnen met bouwen leidt vaak tot afleiding en vertraging.</p>
<h2>Hoe weet je of het werkt?</h2>
<p>Hoe zie je of het werkt? Je team besteedt veel minder tijd aan handmatig werk (60&ndash;80%). Klachten over &ldquo;het systeem&rdquo; verdwijnen. Je kunt nieuwe diensten in weken lanceren in plaats van maanden, en je IT-kosten worden voorspelbaar in plaats van een maandelijkse gok.</p>
<p>Vooral die voorspelbare IT-kosten zijn enorm waardevol&mdash;je kunt daardoor betrouwbare financi&euml;le prognoses maken en toekomstige projecten plannen.</p>
<h2>Klaar om te ontdekken wat mogelijk is?</h2>
<p>Als je geen tijd en geld meer wilt verliezen aan verouderde software, laten we dan samen kijken hoe een gefaseerde, bedrijfsgerichte modernisering jouw MKB kan helpen groeien.</p>
<p>Gebruik je momenteel AWS, Google Cloud, Hetzner of Azure? Dan kunnen we ook kijken naar een overstap naar een cloudprovider die beter bij je past. Mijn doel is om je platform (als dat nog niet het geval is) te containeriseren, zodat het flexibel en verplaatsbaar wordt.</p></body></html>
]]></content>
                    <summary><![CDATA[Het moderniseren van je legacy PHP-systeem draait niet alleen om technologie—het is een slimme zet voor de groei van je MKB. Ontdek hoe een upgrade tijd bespaart, risico’s verlaagt en nieuwe zakelijke kansen opent.]]></summary>
                    <media:content xmlns:media="http://search.yahoo.com/mrss/" url="https://aloia-systems.gumlet.io/?s=7003e0636d274f6d88b2de4cbef3fc87" medium="image" type="image/jpeg" width="640" height="428" />
                  </entry>
<entry>
                    <title><![CDATA[Hoe event sourcing Omoik betrouwbaar, controleerbaar en inzichtelijk maakt]]></title>
                    <link href="https://roelofjanelsinga.nl/articles/event-sourcing-in-omoik/"/>
                    <id>https://roelofjanelsinga.nl/articles/event-sourcing-in-omoik/</id>
                    <updated>2025-07-04T09:26:00+02:00</updated>
                    <published>2025-07-03T12:00:00+02:00</published>
                    <content type="html"><![CDATA[<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
<html><body><h1>Hoe event sourcing Omoik betrouwbaar, controleerbaar en inzichtelijk maakt</h1>
<p><img src="https://aloia-systems.gumlet.io/images/articles/event-sourcing-graphic.png?w=640&amp;h=426&amp;s=94d8cb53ef9c9d84621afea02501c516" alt="Event sourcing graphic" loading="lazy" class="visibility-auto" title="Event sourcing graphic" srcset="https://aloia-systems.gumlet.io/images/articles/event-sourcing-graphic.png?w=320&amp;h=213&amp;mode=crop&amp;crop=smart&amp;s=bb044f5643678b7aeed9e5c5e1767d81 320w,https://aloia-systems.gumlet.io/images/articles/event-sourcing-graphic.png?w=480&amp;h=319&amp;mode=crop&amp;crop=smart&amp;s=45df1b9b5e644abdf5aeea64ad187b6e 480w,https://aloia-systems.gumlet.io/images/articles/event-sourcing-graphic.png?w=640&amp;h=426&amp;mode=crop&amp;crop=smart&amp;s=94db257cde8f23de708f290b998fcce4 640w" sizes="(max-width: 360px) 320px, max-width: 640px) 480px, 640px"></p>
<p>Bij het bouwen van Omoik, het privacyvriendelijke enqu&ecirc;teplatform, kwam ik voor een bekende uitdaging te staan: hoe garandeer je betrouwbaarheid, flexibiliteit en compliance voor klanten, zonder het jezelf of je gebruikers moeilijk te maken? Mijn antwoord: event sourcing.</p>
<p>Event sourcing is niet zomaar een technisch patroon; het is een zakelijke enabler. Het maakt software eenvoudiger te onderhouden, makkelijker uit te breiden, en veel nuttiger voor klanten die gedetailleerde analyses, dashboards en controleerbare gegevens nodig hebben. Laten we eens kijken wat dat in de praktijk betekent.</p>
<h2>Wat is Event Sourcing?</h2>
<p>Ik schreef onlangs een uitgebreidere uitleg over <a href="/artikelen/eventsourcing-in-production/">event sourcing</a>, dus als je nog niet helemaal bekend bent met het concept, neem daar gerust een kijkje. Hier is een korte samenvatting:</p>
<p>In plaats van alleen de huidige staat van je data op te slaan (zoals "enqu&ecirc;te X heeft 42 reacties"), legt event sourcing elke wijziging vast als een event:</p>
<ul>
<li><code>SurveyCreated</code></li>
<li><code>QuestionAdded</code></li>
<li><code>SubmissionCompleted</code></li>
<li><code>SubmissionClosed</code></li>
</ul>
<p>Deze events worden achtereenvolgens opgeslagen in een event store (ik gebruik <a href="https://www.kurrent.io/">kurrent</a> voor <a href="https://omoik.com">Omoik</a>). De huidige staat van een enqu&ecirc;te, of een ander onderdeel van het systeem, wordt vervolgens opgebouwd door deze events af te spelen.</p>
<h3>Waarom zou je deze &ldquo;complexiteit&rdquo; willen?</h3>
<p>Voor ontwikkelaars: Elke stuk code hoeft alleen &eacute;&eacute;n klein, goed gedefinieerd event af te handelen. Geen verstrengelde businesslogica meer die alle mogelijke staten moet overzien. De enige vraag die je moet beantwoorden is: &ldquo;Kan ik dit event opslaan?&rdquo;</p>
<p>Voor bedrijven: Je krijgt een volledige audit trail, de mogelijkheid om trends in de tijd te analyseren, en dashboards die antwoord geven op vragen als &ldquo;wat gebeurde wanneer, en waarom?&rdquo; &ndash; zelfs als je die vragen pas jaren later stelt.</p>
<h2>Technische voordelen: eenvoudigere code en minder context</h2>
<p>Event sourcing breekt complexe processen op in kleine behapbare events. Elke event handler hoeft zich maar op &eacute;&eacute;n ding tegelijk te richten. Dit maakt code makkelijker om te schrijven, testen en debuggen.</p>
<p>Een voorbeeld in Go van het afhandelen van een enqu&ecirc;te-inzending:</p>
<pre><code class="language-golang">type SubmissionAggregate struct {
    Events     []cqrs.Event
    IsStarted  bool
}

func (a *SubmissionAggregate) HandleCommand(ctx context.Context, command cqrs.Command) error {
    switch typedCommand := command.(type) {
    case *StartSurveySubmissionCommand:

        if a.Attributes.IsStarted {
            return nil
        }

        if err := a.ApplyEvent(ctx, &amp;events.SurveyStartedEvent{
            SurveyID:  typedCommand.SurveyID,
            SessionID: typedCommand.SessionID,
            UserAgent: typedCommand.UserAgent,
            Language:  typedCommand.Language,
            Platform:  typedCommand.Platform,
            Url:       typedCommand.Url,
            StartedAt: typedCommand.StartedAt,
        }); err != nil {
            return err
        }
    }
    return nil
}

func (a *SubmissionAggregate) ApplyEvent(ctx context.Context, event cqrs.Event) error {
    a.Events = append(a.Events, event)

    switch typedEvent := event.(type) {
    case *events.SurveyStartedEvent:
        a.IsStarted = true
    }
    return nil
}</code></pre>
<p>Je hebt een aggregate. Die beslist alleen of een event toegepast moet worden op basis van de ontvangen command. Niet meer, niet minder. Elk stukje code is klein, gericht en makkelijk te testen.</p>
<p>Een alternatieve, meer leesbare stijl:</p>
<pre><code class="language-golang">func (a *SubmissionAggregate) StartSubmission(ctx context.Context, cmd events.SurveyStartedEvent) error {

    if a.Attributes.IsStarted {
        return nil
    }

    return a.ApplyEvent(ctx, &amp;events.SurveyStartedEvent{
        SurveyID:  cmd.SurveyID,
        SessionID: cmd.SessionID,
        UserAgent: cmd.UserAgent,
        Language:  cmd.Language,
        Platform:  cmd.Platform,
        Url:       cmd.Url,
        StartedAt: cmd.StartedAt,
    })
}</code></pre>
<p>De implementatie is niet belangrijk &ndash; de events zijn dat wel. Wat je ook kiest als opslagmethode, de events (de feiten) zijn de waarheid.</p>
<h2>Zakelijke voordelen: Analyses, dashboards en compliance</h2>
<p>Techniek is belangrijk, maar als de business geen voordeel ziet, komt event sourcing er niet. Gelukkig zijn er (zeer overtuigende) redenen waarom bedrijven hier ook blij van worden.</p>
<h3>Analyses, zelfs over het verleden</h3>
<p>Omdat elk event wordt opgeslagen, kun je nieuwe rapporten of dashboards bouwen wanneer je maar wilt, zelfs voor data van jaren geleden. Wil je weten hoe de respons veranderde na het toevoegen van een specifieke vraag? Voeg een projector toe, voer alle relevante events in, en je hebt direct een rapport.</p>
<p>Bij traditionele (CRUD) applicaties is dit onmogelijk &ndash; oude data is overschreven en niet terug te halen. Je kunt ook geen historische data simuleren als je ineens een nieuw idee hebt.</p>
<p>Events zijn feiten. Wat je ermee doet is aan jou.</p>
<h3>Moeiteloze dashboards</h3>
<p>Dashboards geven bruikbare inzichten, en met event sourcing zijn ze makkelijk te bouwen en up-to-date te houden. Je hoeft geen complexe queries te draaien of te hopen dat oude data nog accuraat is.</p>
<p>Bij traditionele applicaties moet je:</p>
<ul>
<li>Gecompliceerde databasequeries schrijven</li>
<li>Hopen dat oude data niet is gewijzigd</li>
<li>Hopen dat velden in de database niet zijn overschreven</li>
</ul>
<p>Bij event sourcing is het simpeler:</p>
<pre><code class="language-golang">type SurveyStatistics struct {
    NumberOfViews       uint64
    NumberOfSubmissions uint64
}

func (a *SurveyStatistics) ApplyEvent(ctx context.Context, event cqrs.Event) error {
    switch _ := event.(type) {
    case *events.SurveyStartedEvent:
        a.NumberOfViews++
    case *events.CompletedEvent:
        a.NumberOfSubmissions++
    }
    return nil
}</code></pre>
<p>Na het verwerken van alle events heb je een in-memory model met het aantal views en inzendingen. Zelfs als je geen programmeur bent, is deze code goed te begrijpen.</p>
<h3>Audit trails voor compliance, veiligheid en vertrouwen</h3>
<p>Elke actie is vastgelegd, voorzien van tijdstempel en gebruiker. Dit is essentieel voor klanten die moeten voldoen aan wet- en regelgeving, of transparantie richting hun eigen gebruikers willen tonen.</p>
<p>Voorbeelden van vragen die je hiermee beantwoordt:</p>
<ul>
<li>"Wie heeft deze vraag gewijzigd, en wanneer?"</li>
<li>"Zijn er reacties verwijderd?"</li>
<li>"Wat gebeurde er precies tijdens dat incident vorige maand?"</li>
</ul>
<p>De events liegen niet &ndash; en kunnen niet gewijzigd worden.</p>
<h2>Realistische toepassing: Omoik</h2>
<p>Een praktijkvoorbeeld: bij Omoik vragen klanten vaak om nieuwe manieren om data te analyseren of rapporten te genereren op basis van reacties. Bugs komen ook voor, en kunnen statistieken be&iuml;nvloeden. Event sourcing helpt hier enorm.</p>
<p>Nieuwe features? Voeg gewoon nieuwe event types toe zonder risico op dataverlies of ingewikkelde migraties. Ook bij grotere migraties hoef je geen spanning te hebben &ndash; je past gewoon een projector aan, voedt hem met bestaande events, en voil&agrave;.</p>
<p>En bij bugs die data be&iuml;nvloeden? Dan speel je gewoon het event-log opnieuw af en je statistieken zijn hersteld.</p>
<p>Een ander voorbeeld: aangepaste rapporten. Klanten vragen regelmatig rapporten over periodes waarvoor eerst geen rapporten nodig waren. Omdat elk event bewaard blijft, kan ik alsnog die inzichten geven. Zelfs specifieke vragen als:
<code>Hoeveel bezoekers beantwoordden vraag 1, maar niet vraag 2, v&oacute;&oacute;rdat we vraag 2 wijzigden van "Hoe heb je over ons gehoord?" naar "Hoe heb je onze website gevonden?"</code> &ndash; zijn eenvoudig te beantwoorden.</p>
<p>Dankzij event sourcing kan Omoik snel nieuwe mogelijkheden bieden, zakelijke vragen beantwoorden en betrouwbare data tonen &ndash; zonder de stabiliteit van het platform in gevaar te brengen.</p>
<h2>Moet jij event sourcing gebruiken?</h2>
<p>Ja, het is initieel complexer dan een CRUD-app, maar de winst in betrouwbaarheid, flexibiliteit en inzichten is enorm.</p>
<p>Voor ontwikkelaars: eenvoudiger te bouwen en onderhouden. Bugs zijn makkelijker op te sporen en nieuwe features minder risicovol.</p>
<p>Voor bedrijven: transparantie, compliance en de mogelijkheid om terug te kijken op alles wat ooit gebeurd is.</p>
<h2>Conclusie: Bouwen voor de toekomst</h2>
<p>Event sourcing is een game changer geweest voor Omoik. Het hielp me een platform te bouwen dat technisch sterk is, &eacute;n daadwerkelijk nuttig voor klanten &ndash; of ze nu compliance, analyses of gewoon inzicht willen in het gedrag van hun bezoekers. Het mooiste? Klanten hoeven niet te weten dat Omoik gebouwd is met event sourcing &ndash; het werkt gewoon.</p>
<p>Ben je ge&iuml;nteresseerd in privacyvriendelijke, controleerbare platforms of wil je ontdekken wat event sourcing voor jouw bedrijf kan betekenen? Neem gerust contact met me op via <a href="https://www.linkedin.com/in/roelofjanelsinga/">LinkedIn</a> of stuur me een bericht!</p></body></html>
]]></content>
                    <summary><![CDATA[Ontdek hoe event sourcing het privacyvriendelijke enquêteplatform Omoik aandrijft – met realtime analyses, eenvoudige dashboards en volledige audit trails voor compliance. Lees hoe deze aanpak zowel ontwikkelaars als bedrijven helpt.]]></summary>
                    <media:content xmlns:media="http://search.yahoo.com/mrss/" url="https://aloia-systems.gumlet.io/images/articles/event-sourcing-graphic.png?s=3561d4171927fc3de5805d781f0ee204" medium="image" type="image/jpeg" width="640" height="428" />
                  </entry>
<entry>
                    <title><![CDATA[Hoe kies je de juiste developer voor jouw bedrijf?]]></title>
                    <link href="https://roelofjanelsinga.nl/articles/kies-de-juiste-developer-voor-jouw-bedrijf/"/>
                    <id>https://roelofjanelsinga.nl/articles/kies-de-juiste-developer-voor-jouw-bedrijf/</id>
                    <updated>2025-06-24T19:59:44+02:00</updated>
                    <published>2025-06-30T12:00:00+02:00</published>
                    <content type="html"><![CDATA[<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
<html><body><h1>Hoe kies je de juiste developer voor jouw bedrijf?</h1>
<p><img src="https://aloia-systems.gumlet.io/images/articles/how-to-choose-developer.png?w=640&amp;h=426&amp;s=6d078af5a623cba554f833ba4ea9e205" alt="Choosing the Right Developer" loading="lazy" class="visibility-auto" title="Choosing the Right Developer" srcset="https://aloia-systems.gumlet.io/images/articles/how-to-choose-developer.png?w=320&amp;h=213&amp;mode=crop&amp;crop=smart&amp;s=a3916f1bd5048b7a922b9719f13c4144 320w,https://aloia-systems.gumlet.io/images/articles/how-to-choose-developer.png?w=480&amp;h=319&amp;mode=crop&amp;crop=smart&amp;s=c0735224fc5719ffcfbdd71a861b62a0 480w,https://aloia-systems.gumlet.io/images/articles/how-to-choose-developer.png?w=640&amp;h=426&amp;mode=crop&amp;crop=smart&amp;s=b618f75da0442d3260485e5e502d0b5e 640w" sizes="(max-width: 360px) 320px, max-width: 640px) 480px, 640px"></p>
<p>Dus, je denkt eraan om een developer in te schakelen om je bedrijf soepeler te laten draaien, wat hoofdpijn te automatiseren, of eindelijk al die systemen met elkaar te laten praten? Dat is een grote stap - en eerlijk gezegd kan het best overweldigend zijn als je niet weet waar je moet beginnen.</p>
<p>Laten we samen kijken naar wat er &eacute;cht toe doet als je een developer kiest, zeker als je een MKB-eigenaar of projectmanager bent in Groningen (of waar dan ook in Nederland). Ik heb met veel bedrijven zoals die van jou gewerkt, en ik heb gezien wat werkt - en wat niet.</p>
<h2>1. Begin bij je &eacute;chte probleem, niet bij de techniek</h2>
<p>Voordat je op zoek gaat naar een developer, stel jezelf de vraag:"Wat is nu precies het proces of pijnpunt dat ik wil oplossen?"
Misschien ben je het zat om informatie van je boekingssysteem naar je CRM te kopi&euml;ren, of raak je leads kwijt omdat je data overal verspreid staat. </p>
<p>Hoe duidelijker je je workflow en de knelpunten hebt, hoe makkelijker het wordt voor een developer om je te helpen.</p>
<p>Weet je het niet precies? Geen probleem. Een goede developer stelt je een hoop vragen om dat samen uit te zoeken. (En eerlijk: als ze dat niet doen, is dat een teken dat ze misschien niet de juiste zijn.)</p>
<h2>2. Laat je niet afleiden door jargon</h2>
<p>Je hoeft geen tech-expert te zijn. Wat je w&eacute;l nodig hebt, is iemand die dingen in gewone taal uitlegt en echt luistert naar hoe jouw bedrijf werkt. Als een developer meteen begint over frameworks, cloudplatforms of ingewikkelde afkortingen zonder eerst naar jouw dagelijkse praktijk te vragen, past die misschien niet zo goed bij je.</p>
<p>Let op mensen die vragen stellen als:</p>
<ul>
<li>"Hoe gebruikt jouw team dit systeem nu?"  </li>
<li>"Wie heeft wanneer toegang tot welke informatie?"  </li>
<li>"Wat is het meest frustrerende aan je huidige proces?"</li>
</ul>
<h2>3. Flexibiliteit is belangrijk</h2>
<p>Elk bedrijf is anders. Misschien wil je per uur betalen, of liever een vaste prijs voor het project.
Misschien heb je behoefte aan doorlopende ondersteuning, of juist aan eenmalige hulp. Zorg dat de developer bereid is te werken op een manier die bij jou past.</p>
<p>En maak je geen zorgen als je later extra functies wilt toevoegen - bijna elke klant wil dat! Het belangrijkste is dat je vooraf bespreekt hoe zulke wijzigingen worden opgepakt.</p>
<h2>4. Check hun ervaring (en vraag om verhalen)</h2>
<p>Ervaring telt, maar niet alleen het aantal jaren. Vraag naar vergelijkbare projecten, of nog beter - vraag om verhalen.</p>
<ul>
<li>"Kun je een voorbeeld geven van een bedrijf zoals het mijne dat je hebt geholpen met het koppelen van systemen?"  </li>
<li>"Op welk project ben je het meest trots, en waarom?"</li>
</ul>
<p>Je wilt iemand hebben die al wat verschillende situaties heeft gezien en weet hoe je iets verbetert zonder bestaande processen te blokkeren.</p>
<h2>5. Let op deze groene en rode vlaggen</h2>
<p>Groene vlaggen:</p>
<ul>
<li>Ze stellen veel vragen over jouw bedrijf, niet alleen over techniek.  </li>
<li>Ze willen eerst je workflow in kaart brengen voordat ze beginnen met bouwen.  </li>
<li>Ze leggen dingen graag simpel uit en houden je goed op de hoogte.</li>
</ul>
<p>Rode vlaggen:</p>
<ul>
<li>Ze willen dat je jouw hele proces aanpast aan hun favoriete tool.  </li>
<li>Ze reageren ge&iuml;rriteerd op je vragen of leggen dingen niet duidelijk uit.  </li>
<li>Ze kunnen je geen globale prijs of aanpak geven voor wijzigingen.</li>
</ul>
<h2>6. Prijs is belangrijk, maar niet alles</h2>
<p>Tarieven lopen uiteen. Voor ervaren freelancers is zo&rsquo;n &euro;100 per uur heel normaal in Nederland. Wat belangrijker is: transparantie. Hoe gaan ze om met extra verzoeken, scope-wijzigingen en support na de oplevering? Zorg dat je dit allebei vooraf duidelijk hebt.</p>
<h2>7. De discovery-fase is waar het verschil wordt gemaakt</h2>
<p>Dit is het moment waarop jij en de developer echt op &eacute;&eacute;n lijn komen. Ze moeten je processen uitpluizen, vragen wie wat doet, en een overzicht maken van hoe informatie door je bedrijf stroomt. Slaan ze deze stap over, dan krijg je waarschijnlijk geen oplossing die echt past.</p>
<h2>Bottom line:</h2>
<p>Je hoeft niet alle antwoorden te hebben of "developer" te spreken. Je hebt gewoon iemand nodig die jouw bedrijf wil leren kennen en iets bouwt dat jouw werk makkelijker maakt - niet moeilijker.</p>
<p>Wil je eens sparren over wat er mogelijk is, of gewoon je idee&euml;n bespreken? Ik denk graag met je mee - vrijblijvend.</p></body></html>
]]></content>
                    <summary><![CDATA[Discover how to choose the right developer for your SME. Learn what questions to ask, how to spot red flags, and why understanding your business processes leads to better software solutions.]]></summary>
                    <media:content xmlns:media="http://search.yahoo.com/mrss/" url="https://aloia-systems.gumlet.io/images/articles/how-to-choose-developer.png?s=993306408f6e26994de9903b4cadf57e" medium="image" type="image/jpeg" width="640" height="428" />
                  </entry>
<entry>
                    <title><![CDATA[Systemen bouwen met event sourcing is prachtig]]></title>
                    <link href="https://roelofjanelsinga.nl/articles/eventsourcing-in-production/"/>
                    <id>https://roelofjanelsinga.nl/articles/eventsourcing-in-production/</id>
                    <updated>2025-06-20T13:31:00+02:00</updated>
                    <published>2025-06-20T12:00:00+02:00</published>
                    <content type="html"><![CDATA[<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
<html><body><p><img src="https://images.unsplash.com/photo-1581068414180-050836da1aff?q=80&amp;w=640&amp;h=426&amp;auto=format&amp;fit=crop&amp;ixlib=rb-4.1.0&amp;ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D" alt="Een stroom van events" loading="lazy" class="visibility-auto" title="Een stroom van events" srcset="https://images.unsplash.com/photo-1581068414180-050836da1aff?q=80&amp;w=640&amp;h=426&amp;auto=format&amp;fit=crop&amp;ixlib=rb-4.1.0&amp;ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D 320w,https://images.unsplash.com/photo-1581068414180-050836da1aff?q=80&amp;w=640&amp;h=426&amp;auto=format&amp;fit=crop&amp;ixlib=rb-4.1.0&amp;ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D 480w,https://images.unsplash.com/photo-1581068414180-050836da1aff?q=80&amp;w=640&amp;h=426&amp;auto=format&amp;fit=crop&amp;ixlib=rb-4.1.0&amp;ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D 640w" sizes="(max-width: 360px) 320px, max-width: 640px) 480px, 640px"></p>
<h1>Systemen bouwen met event sourcing is prachtig</h1>
<p>De afgelopen maanden heb ik event sourcing opnieuw ontdekt, en hoe fijn het is om systemen te bouwen die gebruikmaken van deze aanpak. Ik heb hier eerder over geschreven, in <a href="https://roelofjanelsinga.com/articles/event-sourcing-single-source-truth/">2019</a>, maar sindsdien heb ik andere technieken en benaderingen geleerd. De eenvoud van de code die je schrijft met event sourcing is iets waar ik echt van geniet. Het stelt me in staat om systemen te bouwen die flexibel en goed onderhoudbaar zijn.</p>
<p>Een kleine waarschuwing: ik wilde eigenlijk een kort artikel schrijven, maar ik werd te enthousiast en het is wat langer geworden dan bedoeld. Toch is het doel hetzelfde gebleven: ik wil de voordelen van event sourcing benadrukken, en laten zien hoe jij dit ook in je eigen projecten kunt inzetten. Voel je vrij om stukken over te slaan, maar ik raad aan het hele artikel te lezen voor het volledige plaatje.</p>
<h2>Het &ldquo;probleem&rdquo; met CRUD</h2>
<p>Ik heb expres deze subtitel gekozen, omdat ik een probleem wil aanwijzen, niet omdat CRUD slecht is.</p>
<p>Na een paar jaar werken aan een CRUD-app loop je onvermijdelijk tegen beslissingen aan die je in het verleden hebt genomen. Dat is het moment waarop je ziet hoe rommelig alle bedrijfsregels en toenemende complexiteit kunnen worden.</p>
<p>Een veld updaten in een database is makkelijk, totdat je merkt dat de data niet meer logisch is. Je moet dan achterhalen wat er veranderd is, waarom dat gebeurd is en wanneer. Traditionele CRUD biedt geen goede manier om deze veranderingen te volgen, dus debugging kost veel tijd en energie.</p>
<p>Natuurlijk zijn er manieren om dit op te lossen, daar kom ik later op terug.</p>
<h2>CRUD is te technisch</h2>
<p>Idealiter is code niets meer dan een representatie van hoe het bedrijf werkt. Maar CRUD is te technisch voor niet-technische mensen.</p>
<p>Stel je voor: je hebt een e-commerce bestelling die je wilt annuleren. Iemand zegt: &ldquo;Verwijder deze bestelling gewoon.&rdquo; Een junior developer hoort dit en verwijdert letterlijk de bestelling. Opdracht geslaagd, toch?</p>
<p>Maar na wat meer ervaring besef je dat dit niet is wat het bedrijf bedoelde. Ze wilden de bestelling niet meer zien in hun lijst met te verwerken bestellingen. De bestelling hoefde niet meer afgehandeld te worden, en de klant wilde het product of de dienst niet meer.</p>
<p>Als je de bestelling echt verwijdert, verlies je alle context. Je weet niet meer wie de bestelling plaatste, wanneer, of waarom het geannuleerd werd. Over een jaar weet niemand meer waarom het er niet meer is.</p>
<p>De business bedoelt het goed, maar spreekt jouw taal niet. En dat hoeven ze ook niet. Jij als developer moet hun taal spreken. Geen technische termen, geen jargon, gewoon normale woorden.</p>
<p>Daarom gebruiken teams steeds vaker technieken zoals DDD (Domain-Driven Design). DDD draait om het begrijpen van de business en het bouwen van software die daarop aansluit.</p>
<p>Iedereen begrijpt &ldquo;Bestelling geannuleerd&rdquo; in de context van het bedrijf. Je hoeft niet uit te leggen wat &ldquo;Een bestelling verwijderen&rdquo; betekent &mdash; zoiets gebeurt niet in de echte wereld. Je kunt de tijd niet terugdraaien, maar je kunt wel aangeven dat er geen actie meer nodig is.</p>
<p>Ik hoor je denken: klinkt goed, maar hoe werkt dat dan in de praktijk? Waarom zou dit niet gewoon met CRUD kunnen?</p>
<h2>Hoe verschilt event sourcing van CRUD?</h2>
<p>Als je bekend bent met event sourcing, ken je dit voorbeeld misschien al: In een CRUD-applicatie Create, Read, Update en Delete je data in een database. Dat is prima voor veel toepassingen. Totdat iemand je vraagt: &ldquo;Wie heeft deze bestelling geannuleerd?&rdquo;</p>
<p>In een CRUD-app kun je dat niet beantwoorden, tenzij je daar vooraf aan gedacht hebt.</p>
<p>Dus voeg je een audit trail toe. Super! Maar dat lost het alleen op voor toekomstige bestellingen, niet voor bestaande. Je kunt alleen zeggen: &ldquo;Vanaf nu houden we bij wie een bestelling annuleert.&rdquo;</p>
<p>Event sourcing lost dit fundamenteel op. Je maakt geen directe wijzigingen meer in de database, maar je houdt bij wat er is gebeurd: gebeurtenissen.</p>
<ul>
<li><code>OrderPlaced</code></li>
<li><code>OrderCancelled</code></li>
<li><code>OrderRefunded</code></li>
</ul>
<p>Dit zijn feitelijke gebeurtenissen. Ze bevatten metadata: wie het deed, waar, wanneer, etc.</p>
<h2>Read models</h2>
<p>Maar wat doe je met die lijst van gebeurtenissen? Je collega&rsquo;s of klanten willen geen lijst met events. Ze willen weten: &ldquo;Wie annuleerde deze bestelling?&rdquo;</p>
<p>Je hebt dus een representatie nodig van de huidige status van je entiteit, zoals een bestelling. Je bereikt dat door gebeurtenissen toe te passen op een leeg startobject. Bijvoorbeeld:</p>
<pre><code class="language-json">{
  "order_id": "12345",
  "is_cancelled": false,
  "cancelled_by": null
}</code></pre>
<p>Na het toepassen van een <code>OrderCancelled</code> event met:</p>
<pre><code class="language-json">{
  "order_id": "12345",
  "employee_id": "67890"
}</code></pre>
<p>krijg je:</p>
<pre><code class="language-json">{
  "order_id": "12345",
  "is_cancelled": true,
  "cancelled_by": "67890"
}</code></pre>
<p>Je past events toe op een <strong>Aggregate</strong>, daar gaan we nu naar kijken.</p>
<h2>Businessregels</h2>
<p>Klinkt ingewikkeld? Misschien. Maar als je ooit te maken hebt gehad met veranderende bedrijfsregels, dan weet je hoe snel dingen complex worden.</p>
<p>In event sourcing gebruik je commands, zoals <code>CancelOrderCommand</code>. Deze valideert de regels. Als alles klopt, genereer je het <code>OrderCancelled</code> event.</p>
<p>Alle regels zitten netjes bij elkaar in de Aggregate. De events zelf zijn slechts vastgelegde feiten.</p>
<p>Hier een vereenvoudigd voorbeeld in Go:</p>
<pre><code class="language-go">type OrderAggregate struct {
    Events        []Event
    ID            string
    isCancelled   bool
}

func (o *OrderAggregate) HandleCommand(ctx context.Context, command Command) error {
    switch cmd := command.(type) {
        case *CancelOrderCommand:
            if o.isCancelled {
                return fmt.Errorf("order %s is already cancelled", o.ID)
            }

            o.Apply(OrderCancelled{
                ID: cmd.ID,
                CancelledBy: cmd.AdminID,
            })
    }
    return nil
}

func (o *OrderAggregate) Apply(event Event) {
    o.Events = append(o.Events, event)

    switch e := event.(type) {
        case *OrderCancelled:
            o.isCancelled = true
    }
}</code></pre>
<p>Na het toepassen kun je het event opslaan in je event store. Die events zijn nu feiten, en blijven altijd waar.</p>
<h2>Read models, projectors en live modellen</h2>
<p>Je hebt projected read models (zoals database-rijen) en live read models (in-memory gegenereerd door alle events toe te passen).</p>
<p>Met projectors kun je snel nieuwe features toevoegen op basis van bestaande events. Bijvoorbeeld rapporten:</p>
<ul>
<li>Hoeveel bestellingen werden vorige maand geannuleerd?</li>
<li>Hoeveel bestellingen zijn geplaatst in december?</li>
<li>Hoeveel bestellingen zijn geannuleerd &eacute;n later hersteld?</li>
</ul>
<p>Je kunt dit met CRUD doen, maar het is lastiger, foutgevoeliger en moeilijker aanpasbaar.</p>
<h3>Data bekijken op een specifiek moment in de tijd</h3>
<p>Live read models geven je toegang tot de <strong>status van de data op een bepaald moment</strong>. Bijvoorbeeld: wat was de prijs van een product toen de klant vorige week belde?</p>
<p>In event sourcing zie je de vraag &ldquo;Wat vond je van deze site?&rdquo; beantwoord met &ldquo;Ja&rdquo;. Als later de vraag wordt aangepast naar &ldquo;Haat je deze site?&rdquo;, weet je nog steeds dat de gebruiker &ldquo;Ja&rdquo; antwoordde op de oorspronkelijke vraag. Dat kan niet met CRUD.</p>
<h2>Wat met performance?</h2>
<p>Zal dit niet traag zijn? Niet als je het slim aanpakt. Je streams moeten klein blijven. In <a href="https://omoik.com">Omoik</a> leerde ik dit de harde manier.</p>
<p>Ik begon met alle events in &eacute;&eacute;n stream: traag. Nu heeft elke enqu&ecirc;te en elke inzending z&rsquo;n eigen stream (max ~20 events). Supersnel!</p>
<p>Doordat het event ID globaal wordt bijgehouden, weet ik altijd wat de staat van de enqu&ecirc;te was op het moment van inzenden.</p>
<h2>Codewijzigingen breken het verleden niet</h2>
<p>Je kunt je hele applicatie herschrijven, maar de events blijven gelijk. Ze zijn immutable. Dat maakt refactors veilig.</p>
<p>Je past een projector aan, replayt de events, en voil&agrave;: alles is weer correct.</p>
<h2>Conclusie</h2>
<p>Ik kan nog uren doorgaan, maar de boodschap is simpel: event sourcing is krachtig. Het maakt je systemen flexibeler, beter onderhoudbaar en toekomstbestendig.</p>
<p>Gebruik je het nog niet? Geef het een kans. Het is even wennen, maar daarna wil je niet meer terug.</p></body></html>
]]></content>
                    <summary><![CDATA[Het bouwen van systemen met event sourcing is ontzettend leuk. In dit artikel leg ik uit hoe event sourcing je helpt om flexibele en onderhoudbare systemen te bouwen.]]></summary>
                    <media:content xmlns:media="http://search.yahoo.com/mrss/" url="https://images.unsplash.com/photo-1581068414180-050836da1aff" medium="image" type="image/jpeg" width="640" height="428" />
                  </entry>
<entry>
                    <title><![CDATA[Automatisering van Boekingsprocessen - Casestudy]]></title>
                    <link href="https://roelofjanelsinga.nl/articles/automatisering-van-boekingsprocessen/"/>
                    <id>https://roelofjanelsinga.nl/articles/automatisering-van-boekingsprocessen/</id>
                    <updated>2024-09-17T19:23:00+02:00</updated>
                    <published>2024-09-17T12:00:00+02:00</published>
                    <content type="html"><![CDATA[<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
<html><body><h1>Casestudy: Automatisering van Boekingsprocessen voor een Lokale Marketplace</h1>
<p><img src="https://aloia-systems.gumlet.io/images/articles/Black_Flat_Screen_Computer_Monitor_on_White_Wooden_Desk.jpg?w=640&amp;h=426&amp;s=4fa72e5a0e7930667c9dc1596fcb3529" alt="Black Flat Screen Computer Monitor on White Wooden Desk" loading="lazy" class="visibility-auto" title="Black Flat Screen Computer Monitor on White Wooden Desk" srcset="https://aloia-systems.gumlet.io/images/articles/Black_Flat_Screen_Computer_Monitor_on_White_Wooden_Desk.jpg?w=320&amp;h=213&amp;mode=crop&amp;crop=smart&amp;s=0dac2971b17329f610425fefa6b43b48 320w,https://aloia-systems.gumlet.io/images/articles/Black_Flat_Screen_Computer_Monitor_on_White_Wooden_Desk.jpg?w=480&amp;h=319&amp;mode=crop&amp;crop=smart&amp;s=73d21d12683b3cd138277fb0332faa62 480w,https://aloia-systems.gumlet.io/images/articles/Black_Flat_Screen_Computer_Monitor_on_White_Wooden_Desk.jpg?w=640&amp;h=426&amp;mode=crop&amp;crop=smart&amp;s=a9730155e4a21950c6a4af61c4272897 640w" sizes="(max-width: 360px) 320px, max-width: 640px) 480px, 640px"></p>
<p>In de competitieve wereld van de lokale marketplaces was het voor een klant een uitdaging om boekingen effectief te beheren met drie verschillende boekingssystemen. Dit leidde tot een ineffici&euml;nte werkomgeving voor de salesafdeling, die continu moest schakelen tussen systemen om klanten van dienst te zijn.</p>
<h2>Probleemstelling</h2>
<p>De sales afdeling had te maken met aanzienlijke administratieve lasten, wat hen afleidde van hun belangrijkste taak: het ondersteunen van klanten en het sluiten van deals. De noodzaak voor een centrale oplossing werd duidelijk.</p>
<h2>Doelstellingen</h2>
<p>Het belangrijkste doel was om tijd te besparen. De sales afdeling moest zich kunnen concentreren op klantcontact in plaats van administratieve taken.</p>
<h2>Oplossing</h2>
<p>Ik ontwikkelde een applicatie in Laravel die als centraal systeem fungeert voor het beheren van boekingen. Deze applicatie synchroniseert boekingen met externe systemen.</p>
<ul>
<li>Beginnen met &eacute;&eacute;n boekingsysteem hielp bij het cre&euml;ren van een duidelijk "domain object" voor boekingen.</li>
<li>We hebben verschillende procesvragen gesteld, zoals het moment van klantnotificaties en hoe om te gaan met externe boekingen.</li>
<li>Dit leidde tot een coherente automatisering van processen, waarbij alle boekingsinformatie centraal werd beheerd.</li>
</ul>
<h2>Resultaten</h2>
<p>De implementatie leverde aanzienlijke tijdsbesparingen op: elke salesagent bespaart gemiddeld &eacute;&eacute;n uur per dag doordat ze niet meer in de externe systemen hoeven te kijken. Dit resulteerde in een effici&euml;ntere workflow en meer tijd om klanten te bedienen.</p>
<h2>Feedback</h2>
<p>Tijdens het proces kwamen onvoorziene situaties naar voren, zoals de timing van het doorzetten van boekingen na betaling. Deze inzichten benadrukken het belang van flexibiliteit en het stellen van gerichte vragen binnen het automatiseringsproces.</p>
<h2>Lessen Geleerd</h2>
<p>Een flexibele aanpak bij het opzetten van processen en het voortdurend stellen van vragen zijn cruciaal voor een succesvolle implementatie. Dit bevordert niet alleen de snelheid van ontwikkeling maar zorgt ook voor een betere afstemming met de wensen van de klant.</p></body></html>
]]></content>
                    <summary><![CDATA[Ontdek hoe een geautomatiseerd systeem voor boekingen de efficiëntie van een lokale marketplace verbeterde. Bespaar tijd en verhoog de klanttevredenheid met innovatieve oplossingen.]]></summary>
                    <media:content xmlns:media="http://search.yahoo.com/mrss/" url="https://aloia-systems.gumlet.io/?s=7003e0636d274f6d88b2de4cbef3fc87" medium="image" type="image/jpeg" width="640" height="428" />
                  </entry>
<entry>
                    <title><![CDATA[Hoe kies je een databasetype voor een softwareproject?]]></title>
                    <link href="https://roelofjanelsinga.nl/articles/hoe-kies-je-een-databasetype-voor-een-softwareproject/"/>
                    <id>https://roelofjanelsinga.nl/articles/hoe-kies-je-een-databasetype-voor-een-softwareproject/</id>
                    <updated>2023-10-13T14:06:27+02:00</updated>
                    <published>2023-10-13T12:00:00+02:00</published>
                    <content type="html"><![CDATA[<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
<html><body><p><img src="https://aloia-systems.gumlet.io/images/articles/futuristic-database-render.png?w=640&amp;h=426&amp;s=0d98969ad0230a9722cca0cd07b62df8" alt="Futuristische database render" loading="lazy" class="visibility-auto" title="Futuristische database render" srcset="https://aloia-systems.gumlet.io/images/articles/futuristic-database-render.png?w=320&amp;h=213&amp;mode=crop&amp;crop=smart&amp;s=044e3e1431eff93487a5cdeff21bf211 320w,https://aloia-systems.gumlet.io/images/articles/futuristic-database-render.png?w=480&amp;h=319&amp;mode=crop&amp;crop=smart&amp;s=1c0876b2e777add74359ec867a0a4b48 480w,https://aloia-systems.gumlet.io/images/articles/futuristic-database-render.png?w=640&amp;h=426&amp;mode=crop&amp;crop=smart&amp;s=6ce7a0743bc5132259ff41ffc4dd5ae5 640w" sizes="(max-width: 360px) 320px, max-width: 640px) 480px, 640px"></p>
<h1>Hoe kies je een databasetype voor een softwareproject?</h1>
<p>In de wereld van softwareontwikkeling vormen databases het hart van de meeste toepassingen. Deze essenti&euml;le tools dienen als de ruggengraat van elke webapplicatie, voor het opslaan en ophalen van gegevens die de dynamische inhoud waarmee we interageren aandrijven. Bij het starten of uitbreiden van een softwareproject is het kiezen van het juiste databasetype een van de belangrijkste beslissingen die je zult nemen.</p>
<p>In deze blogpost verkennen we de sterke punten en gebruikssituaties van drie populaire databasesystemen: MySQL, MongoDB en Neo4j. Door de voordelen en bijzonderheden van elk systeem te begrijpen, kun je een weloverwogen beslissing nemen die is afgestemd op de unieke behoeften van jouw project.</p>
<h2>Wat is de rol van een database in een softwareproject?</h2>
<p>Laten we, voordat we de verschillende databasetypen bekijken, even stilstaan bij de rol die databases spelen bij softwareontwikkeling. Een database is de opslagplaats waar gegevens worden opgeslagen, beheerd en opgehaald door je applicatie. Of het nu gaat om een blog, een e-commerce platform of een social media netwerk, databases vormen het hart van alle softwareprojecten.</p>
<p>Een goed gekozen databasesysteem kan de prestaties, schaalbaarheid en gegevensintegriteit ten goede komen. Het zorgt ervoor dat je applicatie effici&euml;nt de informatie kan opslaan en ophalen die het nodig heeft om naadloos te werken.</p>
<p>Als je altijd maar &eacute;&eacute;n databasetype hebt gebruikt, vraag je je misschien af waarom je hier zelfs over na moet denken. Elke database slaat gegevens op die je kunt gebruiken. Waarom maakt het databasetype uit? Laten we eens wat dieper ingaan op 3 verschillende databases om daar achter te komen.</p>
<h2>MySQL: De relationele database</h2>
<p><img src="https://aloia-systems.gumlet.io/images/articles/mysql-logo.png?w=640&amp;h=426&amp;s=25168d15cbc8e4141c542c8d1b89a2aa" alt="MySQL logo" loading="lazy" class="visibility-auto" title="MySQL logo" srcset="https://aloia-systems.gumlet.io/images/articles/mysql-logo.png?w=320&amp;h=213&amp;mode=crop&amp;crop=smart&amp;s=8d3e540241d80f01bffd8830ddefe745 320w,https://aloia-systems.gumlet.io/images/articles/mysql-logo.png?w=480&amp;h=319&amp;mode=crop&amp;crop=smart&amp;s=efd2d95356786103c551ca4434ef3805 480w,https://aloia-systems.gumlet.io/images/articles/mysql-logo.png?w=640&amp;h=426&amp;mode=crop&amp;crop=smart&amp;s=2a0b50e11b688eb91d277c471ff6e77e 640w" sizes="(max-width: 360px) 320px, max-width: 640px) 480px, 640px"></p>
<p>MySQL, een populair open-source relationeel databasebeheersysteem, is een betrouwbare keuze voor veel softwaretoepassingen. Het blinkt uit in het structureren van gegevens in tabellen met vooraf gedefinieerde schema's, waardoor het ideaal is voor projecten die gestructureerde, voorspelbare gegevens vereisen.</p>
<ul>
<li><strong>Gebruiksgevallen</strong>: MySQL blinkt uit wanneer je toepassing gestructureerde gegevens met vaste relaties vereist. Het is zeer geschikt voor content management systemen, e-commerce websites en gegevensgestuurde toepassingen.</li>
<li><strong>Tips voor effectieve gegevensmodellering in MySQL</strong>: Effectieve gegevensmodellering in MySQL houdt in dat je een duidelijk schema ontwerpt dat anticipeert op de gegevensbehoeften van je applicatie. Normalisatie is belangrijk om gegevensoverbodigheid te voorkomen en goed ge&iuml;ndexeerde tabellen verbeteren de queryprestaties.</li>
<li><strong>Kies deze database als</strong>: Je project afhankelijk is van gestructureerde, voorspelbare gegevens met goed gedefinieerde relaties en je een robuuste, ACID-conforme database nodig hebt voor gegevensintegriteit en -consistentie.</li>
</ul>
<p>MySQL biedt een betrouwbare, gestructureerde manier om gegevens op te slaan en is vooral effectief als het gaat om voorspelbare gegevens en goed gedefinieerde relaties. Het volgen van ACID principes garandeert de integriteit en consistentie van gegevens. Laten we ons nu eens verdiepen in NoSQL databases, te beginnen met MongoDB, en onderzoeken hoe deze zich onderscheidt van relationele databases.</p>
<h2>MongoDB: De NoSQL Database</h2>
<p><img src="https://aloia-systems.gumlet.io/images/articles/mongodb-logo.png?w=640&amp;h=426&amp;s=45ae9d765fa01fd98fec79c10b88f948" alt="MongoDB logo" loading="lazy" class="visibility-auto" title="MongoDB logo" srcset="https://aloia-systems.gumlet.io/images/articles/mongodb-logo.png?w=320&amp;h=213&amp;mode=crop&amp;crop=smart&amp;s=5454622c331f442dace79aa476f02159 320w,https://aloia-systems.gumlet.io/images/articles/mongodb-logo.png?w=480&amp;h=319&amp;mode=crop&amp;crop=smart&amp;s=da073a3776c960dcae4b2ea379aa17e8 480w,https://aloia-systems.gumlet.io/images/articles/mongodb-logo.png?w=640&amp;h=426&amp;mode=crop&amp;crop=smart&amp;s=b4f9e1ad5d2590152243fc82973407c6 640w" sizes="(max-width: 360px) 320px, max-width: 640px) 480px, 640px"></p>
<p>MongoDB, een toonaangevende NoSQL database, pakt het anders aan. Het is een documentgeori&euml;nteerde database die gegevens opslaat in flexibele, schema-loze documenten, waardoor het een uitstekende keuze is voor projecten die dynamische gegevensstructuren vereisen.</p>
<ul>
<li><strong>Gebruiksgevallen</strong>: MongoDB is zeer geschikt voor toepassingen met ongestructureerde of halfgestructureerde gegevens, zoals sociale netwerken, contentmanagementsystemen met variabele gegevens en IoT-platforms.</li>
<li><strong>Tips voor effectieve datamodellering in MongoDB</strong>: Effectieve datamodellering in MongoDB houdt in dat je de structuur van je gegevens begrijpt en je documenten zo ontwerpt dat ze overeenkomen met de manier waarop je applicatie gegevens benadert. Het biedt de flexibiliteit om je snel aan te passen aan veranderende bedrijfsbehoeften.</li>
<li><strong>Kies deze database als</strong>: Je project dynamische, semi-gestructureerde gegevens bevat en je waarde hecht aan flexibiliteit, schaalbaarheid en snelle iteratie bij de ontwikkeling. Deze database past uitstekend bij toepassingen waarbij de gegevens vaak veranderen.</li>
</ul>
<p>In wezen maken de flexibiliteit en schaalbaarheid van MongoDB het een sterke kanshebber voor projecten met veranderende gegevensvereisten. Bedenk wel dat elk project uniek is en dat de "beste" database afhangt van je specifieke behoeften en de aard van je gegevens. Nu we relationele en documentgeori&euml;nteerde databases hebben behandeld, gaan we verder met het verkennen van de wereld van grafiekdatabases, te beginnen met Neo4j.</p>
<h2>Neo4j: De grafiekdatabase</h2>
<p><img src="https://aloia-systems.gumlet.io/images/articles/neo4j-new-logo.png?w=640&amp;h=426&amp;s=bbeb4c5b9ba929649b381b7a657a338c" alt="Neo4j logo" loading="lazy" class="visibility-auto" title="Neo4j logo" srcset="https://aloia-systems.gumlet.io/images/articles/neo4j-new-logo.png?w=320&amp;h=213&amp;mode=crop&amp;crop=smart&amp;s=319e33a183fac4a2e3be1e3db85a026e 320w,https://aloia-systems.gumlet.io/images/articles/neo4j-new-logo.png?w=480&amp;h=319&amp;mode=crop&amp;crop=smart&amp;s=ed8c7acb22892c57bec12f48b45bad88 480w,https://aloia-systems.gumlet.io/images/articles/neo4j-new-logo.png?w=640&amp;h=426&amp;mode=crop&amp;crop=smart&amp;s=6f71ef5341d4cdb08f1317fd6af64c76 640w" sizes="(max-width: 360px) 320px, max-width: 640px) 480px, 640px"></p>
<p>Neo4j is een grafiekdatabase die is ontworpen om complexe relaties en sterk onderling verbonden gegevens te verwerken. Het is een uitstekende keuze voor projecten die door ingewikkelde netwerken moeten navigeren of grafiekachtige gegevens moeten analyseren.</p>
<ul>
<li><strong>Gebruiksgevallen</strong>: Neo4j is een onmisbaar hulpmiddel voor toepassingen die te maken hebben met sociale netwerken, aanbevelingsmachines, fraudedetectie en elk scenario waarin relaties tussen gegevens en niet de gegevens zelf een kernonderdeel vormen.</li>
<li><strong>Tips voor effectieve gegevensmodellering in Neo4j</strong>: In Neo4j worden gegevens gemodelleerd als knooppunten en relaties. Effectief modelleren houdt in dat je de entiteiten, relaties en eigenschappen in je gegevens identificeert en definieert als knooppunten en randen in een grafiek.</li>
<li><strong>Kies deze database als</strong>: Je project draait om complexe relaties en je op grafieken gebaseerde queries of diepe analyses moet uitvoeren. Het is de ideale keuze voor toepassingen die te maken hebben met onvoorspelbare en zelfs onbekende dieptes of relaties tussen entiteiten.</li>
</ul>
<p>Concluderend is Neo4j fantastisch in het verwerken van complexe relaties en onderling verbonden gegevens, waardoor het een game-changer is voor projecten die te maken hebben met uitgebreide gegevenskoppeling en -analyse. Het is de keuze bij uitstek voor het ontdekken van inzichten uit relaties en het effici&euml;nt navigeren door voorheen onbekende gegevens.</p>
<h2>Conclusie</h2>
<p>Concluderend is de keuze van een databasesysteem een belangrijk aspect van softwareontwikkeling. MySQL, MongoDB en Neo4j bieden elk specifieke voordelen en gebruikssituaties. Door de behoeften van je project zorgvuldig te evalueren, kun je ervoor zorgen dat je gegevens optimaal worden opgeslagen en beheerd, zodat je je apps snel en eenvoudig kunt ontwikkelen.</p></body></html>
]]></content>
                    <summary><![CDATA[Verken de keuzes van databasesystemen en hun unieke voordelen in deze gids. Duik in MySQL, MongoDB en Neo4j en begrijp hun gebruikssituaties en effectieve tips voor gegevensmodellering. Ideaal voor softwareontwikkelaars die de opslag en het beheer van gegevens willen optimaliseren.]]></summary>
                    <media:content xmlns:media="http://search.yahoo.com/mrss/" url="https://aloia-systems.gumlet.io/images/articles/futuristic-database-render.png?s=57dec279dbddb6169e0e5f33d614bed7" medium="image" type="image/jpeg" width="640" height="428" />
                  </entry>
<entry>
                    <title><![CDATA[Caddy gebruiken voor automatische SSL-certificaten met Cloudflare]]></title>
                    <link href="https://roelofjanelsinga.nl/articles/caddy-gebruiken-voor-automatische-ssl-certificaten-met-cloudflare/"/>
                    <id>https://roelofjanelsinga.nl/articles/caddy-gebruiken-voor-automatische-ssl-certificaten-met-cloudflare/</id>
                    <updated>2023-09-23T16:35:04+02:00</updated>
                    <published>2023-09-23T12:00:00+02:00</published>
                    <content type="html"><![CDATA[<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
<html><body><p><img src="https://aloia-systems.gumlet.io/images/articles/caddy.png?w=640&amp;h=426&amp;s=617aae294a483f5ea4d3b8b3c9e885c3" alt="Caddy logo" loading="lazy" class="visibility-auto" title="Caddy logo" srcset="https://aloia-systems.gumlet.io/images/articles/caddy.png?w=320&amp;h=213&amp;mode=crop&amp;crop=smart&amp;s=98caab053e5dbcb24a1b907ad0b14f51 320w,https://aloia-systems.gumlet.io/images/articles/caddy.png?w=480&amp;h=319&amp;mode=crop&amp;crop=smart&amp;s=eaf4398b1c06c41b6aa577a79ba6c236 480w,https://aloia-systems.gumlet.io/images/articles/caddy.png?w=640&amp;h=426&amp;mode=crop&amp;crop=smart&amp;s=830f9a9ac138fc253e29a02b4b8a60a0 640w" sizes="(max-width: 360px) 320px, max-width: 640px) 480px, 640px"></p>
<h1>Caddy gebruiken voor automatische SSL-certificaten met Cloudflare</h1>
<p>Cloudflare is een zegen en een vloek als het gaat om het verzorgen van SSL-certificaten voor je websites en webapplicaties. Cloudflare doet het meeste zware werk en zorgt ervoor dat je beschermd bent tegen aanvallen. Het is echter ook een vloek. Laat het me uitleggen!</p>
<h2>Waarom Cloudflare en het genereren van SSL-certificaten een uitdaging zijn</h2>
<p>Cloudflare fungeert als een proxy tussen het internet en jouw webserver. Dit is geweldig omdat ze verdacht gedrag kunnen filteren en je webserver kunnen beschermen tegen aanvallen. De aanvaller zal nooit het IP-adres van je server kunnen achterhalen, omdat dit verborgen wordt gehouden door Cloudflare.</p>
<p>Dit is echter ook een probleem. Bij het genereren van SSL-certificaten moet de provider kunnen controleren of de server die het certificaat aanvraagt ook echt is wie hij zegt dat hij is. Certbot heeft bijvoorbeeld een externe server nodig om jouw server te bereiken om te verifi&euml;ren dat de domeinnaam naar de aanvragende server wijst. Alleen als het dit kan verifi&euml;ren, zal het een SSL-certificaat genereren voor dat domein.</p>
<p>Het probleem is dat je Cloudflare nog steeds in het midden van deze interactie hebt. Het verzoek van de externe server zal nooit jouw webserver bereiken, dus het kan niet controleren of de domeinnaam naar jouw server wijst. Je kunt dit omzeilen door de Cloudflare proxy tijdelijk uit te schakelen en deze controle uit te voeren, maar nu ben je niet beschermd. En wat gebeurt er als het tijd is om je certificaat te vernieuwen? Ga je dan elke keer de Cloudflare proxy tijdelijk uitschakelen? Ik denk het niet.</p>
<h2>Hoe genereert Caddy SSL-certificaten achter Cloudflare?</h2>
<p>Dus ik hoor je vragen: "Zelfs als je Caddy gebruikt om deze SSL-certificaten automatisch te genereren, loop je tegen dezelfde problemen aan". En daar heb je gelijk in. Caddy heeft echter een hele mooie plugin die je kunt installeren die interageert met de Cloudflare API om DNS uitdagingen voor LetsEncrypt op te lossen.</p>
<p>De voordelen hiervan zijn fantastisch, want je krijgt:</p>
<ul>
<li>HTTPS tussen jouw server en Cloudflare EN HTTPS tussen Cloudflare en jouw bezoekers.</li>
<li>Nul, ja echt nul, onderhoud als het gaat om SSL-certificaten. Caddy genereert automatisch nieuwe certificaten en je hoeft nooit meer te knoeien met Cloudflare.</li>
</ul>
<p>Als Caddy zelf je nog niet enthousiast heeft gemaakt over webservers, dan zal de gedachte aan nul onderhoud en geen gedoe met Cloudflare dat wel doen. Laten we eens kijken hoe we dit kunnen integreren.</p>
<h2>Hoe de Cloudflare DNS module te integreren in Caddy met Docker</h2>
<p>Het docker gedeelte van deze integratie is optioneel, maar ik draai liever al mijn applicaties in containers, inclusief mijn Caddy installatie. Dus je kunt dat deel volgen of overslaan, jouw keuze.</p>
<p>Eerst moeten we <a href="https://github.com/caddyserver/xcaddy">caddyserver/xcaddy</a> gebruiken om een aangepaste binary voor Caddy te bouwen. Caddy is geschreven in Go, dus we moeten onze binary compileren om de Cloudflare plugin toe te voegen.</p>
<p>Dat kun je doen met dit commando:</p>
<pre><code>$ xcaddy build \
    --with github.com/caddy-dns/cloudflare</code></pre>
<p>Dit commando maakt een binair bestand aan dat de basisinstallatie van Caddy bevat en voegt de Cloudflare DNS-module toe. In een multi-stage docker image ziet dit er als volgt uit:</p>
<pre><code>FROM caddy:2.6.1-builder AS caddy-builder

RUN xcaddy build \
    --with github.com/caddy-dns/cloudflare

FROM caddy:2.6.1-alpine

COPY --from=caddy-builder /usr/bin/caddy /usr/bin/caddy</code></pre>
<p>De reden dat ik dit in een docker image met meerdere fasen plaats, in plaats van het in 1 fase bloot te leggen, is de uiteindelijke grootte van het image. Het caddy builder image is vrij groot, omdat het alle ontwikkelingssoftware bevat. Je hebt niets hiervan nodig in productie. Alles wat je nodig hebt is de resulterende Go binary in <code>/usr/bin/caddy</code>.</p>
<p>Een van de nadelen is dat het bouwen van je eigen Caddy binary niet het snelste proces is. Gelukkig hoef je dit niet vaak te doen, dus het is een goed idee om je eigen Caddy basisimage te publiceren (het Dockerbestand hierboven) en dat mee te nemen bij het bouwen van je uiteindelijke applicatie.</p>
<p>Als voorbeeld maak ik een basisimage van het Dockerfile hierboven en noem dit: <code>roelofjanelsinga/caddy-cloudflare</code></p>
<p>Ik kan dit nu als volgt gebruiken voor het hosten van mijn webapp:</p>
<pre><code>FROM php:8.1-cli AS build-env
COPY --chown=www:www . /var/www/html
WORKDIR /var/www/html

# Voer enkele andere bouwstappen uit, zoals "npm run build" en "composer install".

FROM roelofjanelsinga/caddy-cloudflare:latest

COPY --from=build-env /var/www/html /var/www/html
COPY ./docker/caddy/Caddyfile /etc/caddy/Caddyfile</code></pre>
<p>Nogmaals, dit is een multi-stage build om een zo klein mogelijk image te krijgen. In de tweede stap gebruik ik het aangepaste Caddy image, kopieer ik mijn projectbestanden van de bouwstap naar het uiteindelijke image en voeg ik een aangepast Caddybestand toe met mijn domeinconfiguratie. Deze image kan worden geserveerd en zorgt automatisch voor SSL.</p>
<h2>De Cloudflare API Token krijgen</h2>
<p>In het aangepaste Caddybestand moeten we een regel toevoegen om Caddy te vertellen dat we Cloudflare willen gebruiken voor onze DNS-uitdagingen. Laat me je eerst een voorbeeld geven van mijn configuratie:</p>
<pre><code>https://mydomain.com {

    root * /var/www/html/public
    encode zstd gzip
    file_server

    tls {
        dns cloudflare {env.CF_API_TOKEN}
        resolvers 1.1.1.1
    }

}</code></pre>
<p>Houd in gedachten dat dit een kale, niet-productie configuratie is. Het is alleen bedoeld om te laten zien hoe dit proces werkt.</p>
<p>In de TLS-configuratie hebben we aangegeven dat Cloudflare moet worden gebruikt voor DNS-uitdagingen en je ziet een omgevingsvariabele voor een Cloudflare API-token.</p>
<p>Laten we eens kijken hoe we dat token kunnen krijgen:</p>
<ol>
<li>Log in bij Cloudflare en ga naar het domein waarvoor je Caddy wilt inschakelen.</li>
<li>Aan de rechterkant zie je een gedeelte met de kop "API". Klik op "Get your API token":
<img src="https://aloia-systems.gumlet.io/images/articles/create-api-token.png?w=640&amp;h=426&amp;s=c93a6447fd9eaa637b624a60e7da7ef5" alt="Krijg je API token" loading="lazy" class="visibility-auto" title="Krijg je API token" srcset="https://aloia-systems.gumlet.io/images/articles/create-api-token.png?w=320&amp;h=213&amp;mode=crop&amp;crop=smart&amp;s=5126b42072fd3a258109abfc753af847 320w,https://aloia-systems.gumlet.io/images/articles/create-api-token.png?w=480&amp;h=319&amp;mode=crop&amp;crop=smart&amp;s=17d0e9679431ef886239faa09cd47c2f 480w,https://aloia-systems.gumlet.io/images/articles/create-api-token.png?w=640&amp;h=426&amp;mode=crop&amp;crop=smart&amp;s=30b4f06a27fc724900fc29518d566611 640w" sizes="(max-width: 360px) 320px, max-width: 640px) 480px, 640px"></li>
<li>Klik onder het blok API-tokens op "Create Token":
<img src="https://aloia-systems.gumlet.io/images/articles/user-api-tokens.png?w=640&amp;h=426&amp;s=ab707ca221d0938157d4b343afba3c29" alt="User API tokens" loading="lazy" class="visibility-auto" title="User API tokens" srcset="https://aloia-systems.gumlet.io/images/articles/user-api-tokens.png?w=320&amp;h=213&amp;mode=crop&amp;crop=smart&amp;s=ab4557e50d4fed243d4e35064d7558da 320w,https://aloia-systems.gumlet.io/images/articles/user-api-tokens.png?w=480&amp;h=319&amp;mode=crop&amp;crop=smart&amp;s=a733afbe0fa4ddde288c968d82476da8 480w,https://aloia-systems.gumlet.io/images/articles/user-api-tokens.png?w=640&amp;h=426&amp;mode=crop&amp;crop=smart&amp;s=721dc8411a1953b267a98039fc2b5818 640w" sizes="(max-width: 360px) 320px, max-width: 640px) 480px, 640px"></li>
<li>Scroll op de pagina "User API Tokens" naar beneden en druk op "Get started" in het gedeelte Aangepaste tokens aanmaken:
<img src="https://aloia-systems.gumlet.io/images/articles/create-custom-token.png?w=640&amp;h=426&amp;s=19457d5fa20dba1a6aedc10230d46123" alt="Krijg je API token" loading="lazy" class="visibility-auto" title="Krijg je API token" srcset="https://aloia-systems.gumlet.io/images/articles/create-custom-token.png?w=320&amp;h=213&amp;mode=crop&amp;crop=smart&amp;s=ac4f68cd97c1000735db0ed594f6d08d 320w,https://aloia-systems.gumlet.io/images/articles/create-custom-token.png?w=480&amp;h=319&amp;mode=crop&amp;crop=smart&amp;s=1975360214623a2c6a1664e898dd0fcc 480w,https://aloia-systems.gumlet.io/images/articles/create-custom-token.png?w=640&amp;h=426&amp;mode=crop&amp;crop=smart&amp;s=5f12e8360c38c87c8d5c0a19ade192ba 640w" sizes="(max-width: 360px) 320px, max-width: 640px) 480px, 640px"></li>
<li>Geef je token een beschrijvende naam en voeg 2 rechten toe:
<ol>
<li>Zone - Zone - Read</li>
<li>Zone - DNS - Edit
<img src="https://aloia-systems.gumlet.io/images/articles/create-custom-token-settings.png?w=640&amp;h=426&amp;s=548e6145819765b3c54ba2c32981df01" alt="API Token instellingen" loading="lazy" class="visibility-auto" title="API Token instellingen" srcset="https://aloia-systems.gumlet.io/images/articles/create-custom-token-settings.png?w=320&amp;h=213&amp;mode=crop&amp;crop=smart&amp;s=542c76337232b443583189277f9677e0 320w,https://aloia-systems.gumlet.io/images/articles/create-custom-token-settings.png?w=480&amp;h=319&amp;mode=crop&amp;crop=smart&amp;s=45e6845a23abba66626f4ae6b9f04e4c 480w,https://aloia-systems.gumlet.io/images/articles/create-custom-token-settings.png?w=640&amp;h=426&amp;mode=crop&amp;crop=smart&amp;s=b56e094c3539a9ae59bd1cd902fdc88e 640w" sizes="(max-width: 360px) 320px, max-width: 640px) 480px, 640px"></li>
</ol></li>
<li>Klik op "Continue to summary" en je zou nu je API-token moeten zien.</li>
</ol>
<h2>De Cloudflare API Token gebruiken met Caddy</h2>
<p>Nu je het API token hebt, is de eenvoudigste manier om dit te gebruiken door het op te nemen in je docker-compose instellingen:</p>
<p><img src="https://aloia-systems.gumlet.io/images/articles/caddy-env-in-docker-compose.png?w=640&amp;h=426&amp;s=eaeb393fee9599a2be8017ecfbaa5d19" alt="Cloudflare API-sleutel in docker-compose" loading="lazy" class="visibility-auto" title="Cloudflare API-sleutel in docker-compose" srcset="https://aloia-systems.gumlet.io/images/articles/caddy-env-in-docker-compose.png?w=320&amp;h=213&amp;mode=crop&amp;crop=smart&amp;s=0760360e9b42d2d273ed10140e5b72f2 320w,https://aloia-systems.gumlet.io/images/articles/caddy-env-in-docker-compose.png?w=480&amp;h=319&amp;mode=crop&amp;crop=smart&amp;s=d9bbdf5bb5f1444d9a0801d56acd5ded 480w,https://aloia-systems.gumlet.io/images/articles/caddy-env-in-docker-compose.png?w=640&amp;h=426&amp;mode=crop&amp;crop=smart&amp;s=f25b8a853cb6f6a36d8382ef96a2a5d8 640w" sizes="(max-width: 360px) 320px, max-width: 640px) 480px, 640px"></p>
<p>Maar je kunt deze omgevingssleutel leveren op elke manier die voor jou werkt. Nu, nadat je je caddy container hebt opgestart, zul je merken dat het meteen probeert (en slaagt) om DNS uitdagingen uit te voeren via Cloudflare en SSL certificaten te genereren voor je applicatie.</p>
<p>Je hebt nu automatische SSL-certificaten zolang je Caddy gebruikt en je hoeft nooit meer te knoeien met Cloudflare. Best makkelijk, toch?</p></body></html>
]]></content>
                    <summary><![CDATA[Ontdek de eenvoud van het instellen van SSL-certificaten met Caddy en Cloudflare in deze uitgebreide gids. Leer hoe je de Cloudflare DNS module in Caddy kunt integreren met Docker, een Cloudflare API token kunt aanmaken en je token kunt gebruiken met Caddy voor het automatisch genereren van SSL certificaten. Zeg vaarwel tegen het gedoe van handmatig SSL-certificaat onderhoud!]]></summary>
                    <media:content xmlns:media="http://search.yahoo.com/mrss/" url="https://aloia-systems.gumlet.io/?s=7003e0636d274f6d88b2de4cbef3fc87" medium="image" type="image/jpeg" width="640" height="428" />
                  </entry>
<entry>
                    <title><![CDATA[De Top 10 SEO-fouten die jouw website-ranking schaden]]></title>
                    <link href="https://roelofjanelsinga.nl/articles/top-10-seo-fouten-die-je-ranking-schaden/"/>
                    <id>https://roelofjanelsinga.nl/articles/top-10-seo-fouten-die-je-ranking-schaden/</id>
                    <updated>2023-05-01T17:30:00+02:00</updated>
                    <published>2023-05-01T12:00:00+02:00</published>
                    <content type="html"><![CDATA[<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
<html><body><p><img src="https://aloia-systems.gumlet.io/images/articles/frustrated-business-owner-1.png?w=640&amp;h=426&amp;s=217619f800d714aac9da1d4a8877ffa5" alt="Frustrated business owner" loading="lazy" class="visibility-auto" title="Frustrated business owner" srcset="https://aloia-systems.gumlet.io/images/articles/frustrated-business-owner-1.png?w=320&amp;h=213&amp;mode=crop&amp;crop=smart&amp;s=ce7b174405ae2aa5f72ad5ee1383182d 320w,https://aloia-systems.gumlet.io/images/articles/frustrated-business-owner-1.png?w=480&amp;h=319&amp;mode=crop&amp;crop=smart&amp;s=ef9673bfb8d9e02292cc26b07bf0432f 480w,https://aloia-systems.gumlet.io/images/articles/frustrated-business-owner-1.png?w=640&amp;h=426&amp;mode=crop&amp;crop=smart&amp;s=dbf5b19e827380a56ae9a16aacd7c8fa 640w" sizes="(max-width: 360px) 320px, max-width: 640px) 480px, 640px"></p>
<h1>De Top 10 SEO-fouten die jouw website-ranking schaden</h1>
<p>Zoekmachineoptimalisatie (SEO) is essentieel voor elke website die hoger wil scoren op zoekmachines zoals Google, Bing en Yahoo. Hoe beter de SEO van uw website, hoe groter de kans op het aantrekken van meer bezoekers, leads en verkopen. Veel website-eigenaren maken echter SEO-fouten die hun website-ranking schaden, waardoor ze potenti&euml;le klanten en omzet mislopen. In deze blogpost bespreek ik de top 10 SEO-fouten die u moet vermijden om uw website-ranking te verbeteren en meer klanten aan te trekken.</p>
<h2>Het negeren van zoekwoordonderzoek</h2>
<p>Zoekwoordonderzoek is een van de belangrijkste stappen in SEO. Het is essentieel om te weten waar uw doelgroep online naar zoekt en welke zoekwoorden ze gebruiken. Door de juiste zoekwoorden te onderzoeken en ze te gebruiken in uw inhoud, meta-titels, beschrijvingen en tags, kunt u de relevantie van uw website voor zoekmachines vergroten en meer organisch verkeer aantrekken.</p>
<h2>Het niet optimaliseren van titeltags en meta-beschrijvingen</h2>
<p>Titeltags en meta-beschrijvingen zijn cruciale elementen die zoekmachines helpen begrijpen waar uw website over gaat. Als ze niet zijn geoptimaliseerd, kunnen zoekmachines onnauwkeurige of irrelevante informatie weergeven in de zoekresultaten, wat leidt tot lagere click-through-rates (CTR). Zorg ervoor dat uw titeltags en meta-beschrijvingen uw inhoud nauwkeurig beschrijven en uw doelzoekwoorden bevatten.</p>
<h2>Het gebruik van duplicaatinhoud</h2>
<p>Zoekmachines hechten waarde aan originele inhoud en duplicaatinhoud kan uw website-ranking schaden. Vermijd het kopi&euml;ren van inhoud van andere websites of het gebruik van dezelfde inhoud op meerdere pagina's van uw website. Maak in plaats daarvan unieke, hoogwaardige inhoud die waarde toevoegt voor uw publiek.</p>
<h2>Het verwaarlozen van mobiele optimalisatie</h2>
<p>Mobiele apparaten zijn goed voor meer dan de helft van al het internetverkeer. Als uw website niet is geoptimaliseerd voor mobiele apparaten, loopt u een aanzienlijk aantal potenti&euml;le bezoekers mis. Zorg ervoor dat uw website mobielvriendelijk is, snel laadt en gemakkelijk te navigeren is op kleine schermen.</p>
<h2>Het negeren van paginasnelheid</h2>
<p>Paginasnelheid is een cruciale rankingfactor. Langzaam ladende pagina's kunnen bounce-rates verhogen, wat een negatieve invloed heeft op de SEO van uw website. Optimaliseer de afbeeldingen van uw website, verminder HTTP-verzoeken, minimaliseer CSS- en JavaScript-bestanden en gebruik een content delivery network (CDN) om uw paginasnelheid te verbeteren.</p>
<h2>Niet Gebruiken van Interne Linking</h2>
<p>Interne linking helpt zoekmachines de structuur van je website en de relevantie van je inhoud te begrijpen. Het houdt ook bezoekers langer op je website, wat de betrokkenheid verbetert en het bouncepercentage verlaagt. Gebruik interne linking om gerelateerde inhoud met elkaar te verbinden en bezoekers te begeleiden naar relevante pagina's op je website.</p>
<h2>Verwaarlozing van Externe Linking</h2>
<p>Externe links van websites met een hoge autoriteit kunnen de autoriteit van je website vergroten en je ranking verbeteren. Wees echter voorzichtig met de kwaliteit en relevantie van de externe links die je gebruikt. Vermijd spammy of lage kwaliteit links die de reputatie van je website kunnen schaden.</p>
<h2>Niet Gebruiken van Alt Tags voor Afbeeldingen</h2>
<p>Alt tags helpen zoekmachines de inhoud van afbeeldingen op je website te begrijpen. Ze verbeteren ook de toegankelijkheid voor bezoekers met een visuele beperking. Zorg ervoor dat je beschrijvende alt tags gebruikt die je afbeeldingen nauwkeurig beschrijven en je doelzoekwoorden bevatten.</p>
<h2>Verwaarlozing van Social Media</h2>
<p>Social media kan een uitstekende bron zijn van verkeer en backlinks voor je website. Zorg ervoor dat je je inhoud promoot op social media platforms zoals Facebook, Twitter, LinkedIn en Instagram, en stimuleer sociale deling om je bereik te vergroten.</p>
<h2>Teveel Focussen op Rankings</h2>
<p>Hoewel rankings belangrijk zijn, zijn ze niet de enige maatstaf voor SEO-succes. Richt je in plaats daarvan op het cre&euml;ren van hoogwaardige, waardevolle inhoud die aan de behoeften van je doelgroep voldoet. Door waarde te bieden aan je bezoekers, trek je meer verkeer aan, verbeter je de betrokkenheid en uiteindelijk meer leads en verkoop.</p>
<p>Kortom, het vermijden van deze veelvoorkomende SEO-fouten kan helpen om de ranking van je website te verbeteren en meer verkeer naar je website te leiden. Het is belangrijk om SEO prioriteit te geven en er continu aan te werken om op lange termijn succes te behalen in je online bedrijf.</p></body></html>
]]></content>
                    <summary><![CDATA[Heb je moeite om de ranking van je website op zoekmachines te verbeteren? Bekijk deze top 10 lijst van veelvoorkomende SEO-fouten die de zichtbaarheid van je website kunnen schaden. Leer hoe je deze fouten kunt vermijden en je SEO kunt verbeteren voor langdurig succes in je online bedrijf.
]]></summary>
                    <media:content xmlns:media="http://search.yahoo.com/mrss/" url="https://aloia-systems.gumlet.io/images/articles/frustrated-business-owner-1.png?s=154ba424bf9aba442df55b5cd129175d" medium="image" type="image/jpeg" width="640" height="428" />
                  </entry>
<entry>
                    <title><![CDATA[Verklein je Docker Image wanneer je gebruik maakt van de League Flysystem s3 adapter]]></title>
                    <link href="https://roelofjanelsinga.nl/articles/verklein-docker-image-grootte-laravel-aws-dependency/"/>
                    <id>https://roelofjanelsinga.nl/articles/verklein-docker-image-grootte-laravel-aws-dependency/</id>
                    <updated>2023-01-22T12:05:29+01:00</updated>
                    <published>2023-01-22T12:00:00+01:00</published>
                    <content type="html"><![CDATA[<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
<html><body><p><img src="https://aloia-systems.gumlet.io/images/articles/docker.png?w=640&amp;h=426&amp;s=9501ae7147a8f901d8226991fc5613e5" alt='"Docker"' loading="lazy" class="visibility-auto" title='"Docker"' srcset="https://aloia-systems.gumlet.io/images/articles/docker.png?w=320&amp;h=213&amp;mode=crop&amp;crop=smart&amp;s=eab02f3a5aab1f7d79b42b44dc14e09e 320w,https://aloia-systems.gumlet.io/images/articles/docker.png?w=480&amp;h=319&amp;mode=crop&amp;crop=smart&amp;s=3b68ecb3875f1751c0d79f7ade89a61c 480w,https://aloia-systems.gumlet.io/images/articles/docker.png?w=640&amp;h=426&amp;mode=crop&amp;crop=smart&amp;s=6a6c92b42f180bfd8aec4875a16de695 640w" sizes="(max-width: 360px) 320px, max-width: 640px) 480px, 640px"></p>
<h1>Verklein je Docker Image wanneer je gebruik maakt van de League Flysystem s3 adapter</h1>
<p>Als je je PHP applicaties deployed d.m.v. Docker images en je werkt met S3 als filesystem met Flysystem, dan weet je dat je Docker image niet klein zal zijn.
Flysystem is een fantastische package voor interactie met het bestandssysteem en het toevoegen van ondersteuning voor interactie met een S3 bucket is heel eenvoudig, maar het komt met het nadeel dat je de enorme AWS PHP SDK erbij moet installeren.</p>
<p>De huidige AWS PHP SDK bevat alle classes voor elke AWS service, zelfs als je nooit van plan bent iets anders dan S3 te gebruiken. De auteur van Flysystem (Frank de Jonge) heeft dit al gemarkeerd als een probleem, omdat de hele AWS PHP SDK 29mb groot is. Je kunt die discussie hier vinden: <a href="https://github.com/aws/aws-sdk-php/discussions/2420">Reducing package size</a>.</p>
<p>Deze enorme SDK is moeilijk uit te leggen als je maar een heel klein beetje van de functionaliteit nodig hebt, dus laten we dat oplossen!</p>
<h2>Verwijder alle ongebruikte dependencies</h2>
<p>Als antwoord hierop heeft het AWS-team een mogelijke oplossing voorgesteld, die weinig van jou als ontwikkelaar vraagt, maar je wel 28mb bespaart!
Het AWS-team heeft een callback gemaakt die je kunt toevoegen aan je <code>composer.json</code> en die alle diensten verwijdert die je niet van plan bent te gebruiken: <a href="https://github.com/aws/aws-sdk-php/tree/master/src/Script/Composer">Removing Unused Services</a>.</p>
<p>Dit zijn alle wijzigingen die je moet aanbrengen in je <code>composer.json</code> en het zal onmiddellijk je Docker image kleiner maken zonder de geweldige functionaliteit of <code>league/flysystem</code> te verliezen:</p>
<pre><code class="language-json">{
  "require": {
    "league/flysystem-aws-s3-v3": "^1.0"
  },
  "scripts": {
    "pre-autoload-dump": [
      "Aws\\Script\\Composer\\Composer::removeUnusedServices"
    ]
  },
  "extra": {
    "aws/aws-sdk-php": [
      "S3"
    ]
  }
}</code></pre>
<p>Met de <code>pre-autoload-dump</code> hook kun je een taak toevoegen aan het composer proces, dat in dit geval het <code>composer.json</code> bestand leest en bepaalt welke services je wilt behouden. Het zal alle andere services uit de SDK verwijderen. Er zijn een paar services die altijd worden opgenomen, ongeacht of je ze gebruikt of niet:</p>
<ul>
<li>Kms </li>
<li>S3</li>
<li>SSO</li>
<li>Sts</li>
</ul>
<p>Het AWS-team heeft deze namespaces gemarkeerd als "onveilig om te verwijderen", zodat ze altijd in de dependencies worden opgenomen.</p>
<p>De configuratie in de <code>extra</code> key bevat een lijst van de namespaces die je wilt behouden.
Omdat ik alleen de S3 namespace gebruik, is dit de enige dienst die ik vermeld.
Technisch gezien hoef ik dit niet te doen, omdat deze namespace nooit verwijderd zal worden door deze Composer hook, maar ik wil graag expliciet zijn over mijn dependencies.</p>
<p>Dus als je probeert je Docker image kleiner te maken en je gebruikt Flysystem met de S3 adapter, implementeer dit dan zeker in je project! Het zal je vele kostbare megabytes besparen!</p></body></html>
]]></content>
                    <summary><![CDATA[Flysystem is een fantastische bibliotheek voor interactie met het bestandssysteem en het toevoegen van ondersteuning voor interactie met een S3 bucket is heel eenvoudig, maar het komt met het nadeel dat je de enorme AWS PHP SDK erbij moet betrekken. Laten we dat oplossen!]]></summary>
                    <media:content xmlns:media="http://search.yahoo.com/mrss/" url="https://aloia-systems.gumlet.io/images/articles/docker.png?s=56ecb8b4a2b27b40b75ab1973c41310f" medium="image" type="image/jpeg" width="640" height="428" />
                  </entry>
<entry>
                    <title><![CDATA[Hoe gebruik je step debugging in PHP met Xdebug 3 en PHPStorm]]></title>
                    <link href="https://roelofjanelsinga.nl/articles/hoe-gebruik-je-step-debugging-in-php-met-xdebug-3-en-phpstorm/"/>
                    <id>https://roelofjanelsinga.nl/articles/hoe-gebruik-je-step-debugging-in-php-met-xdebug-3-en-phpstorm/</id>
                    <updated>2022-12-29T14:56:59+01:00</updated>
                    <published>2022-12-29T12:00:00+01:00</published>
                    <content type="html"><![CDATA[<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
<html><body><p><img src="https://aloia-systems.gumlet.io/images/articles/xdebugging-in-phpstorm-cover.jpg?w=640&amp;h=426&amp;s=8aa567015c1540f6dec894f2aac3f4bf" alt="Xdebug in PHPStorm" loading="lazy" class="visibility-auto" title="Xdebug in PHPStorm" srcset="https://aloia-systems.gumlet.io/images/articles/xdebugging-in-phpstorm-cover.jpg?w=320&amp;h=213&amp;mode=crop&amp;crop=smart&amp;s=2d169de2cb949292f9f583a049a0ec1f 320w,https://aloia-systems.gumlet.io/images/articles/xdebugging-in-phpstorm-cover.jpg?w=480&amp;h=319&amp;mode=crop&amp;crop=smart&amp;s=c08a15011e5f44a16588d9a705b32c64 480w,https://aloia-systems.gumlet.io/images/articles/xdebugging-in-phpstorm-cover.jpg?w=640&amp;h=426&amp;mode=crop&amp;crop=smart&amp;s=a35cf7061957c9a7a17ba0127cdf6770 640w" sizes="(max-width: 360px) 320px, max-width: 640px) 480px, 640px"></p>
<h1>Hoe gebruik je step debugging in PHP met Xdebug 3 en PHPStorm</h1>
<p>Wil je je PHP code effici&euml;nter debuggen? Dat kan heel eenvoudig met Xdebug 3 en PHPStorm. Met deze instelling kun je regel voor regel door je code stappen, zodat je beter kunt zien hoe je programma wordt uitgevoerd en eventuele problemen snel kunt opsporen. In deze post laat ik je zien hoe je stapsgewijs kunt debuggen in PHP met Xdebug 3 en PHPStorm.</p>
<p>Dit zijn de stappen die we gaan doen om step debugging in PHPStorm in te schakelen:</p>
<ol>
<li>Xdebug 3 configureren</li>
<li>PHPStorm configureren</li>
<li>Debugging testen</li>
</ol>
<p>Het is verrassend eenvoudig om step debugging voor PHP in te schakelen, dus laten we beginnen!</p>
<h2>Xdebug 3 configureren om step debugging in te schakelen</h2>
<p>De eerste stap om stap debugging voor PHP in te schakelen is het configureren van Xdebug 3. In deze gids ga ik ervan uit dat je PHP en Xdebug 3 al ge&iuml;nstalleerd hebt, dus als je dat nog niet gedaan hebt, doe dat dan eerst voordat je verder gaat met dit proces.</p>
<p>Eerst moeten we uitzoeken welke configuratie we moeten veranderen om step debugging voor Xdebug 3 in te schakelen. Een gemakkelijke manier om dit te doen is door een voorbeeld PHP applicatie te draaien, in mijn voorbeeld Laravel, en <code>phpinfo();</code> in het hoofdscript te plaatsen (<code>public/index.php</code> voor Laravel). Dit naaront een lijst van alle geladen configuraties in de sectie "Extra .ini bestanden geparsed". Hier vind je ook een lijst voor Xdebug. </p>
<p><img src="https://aloia-systems.gumlet.io/images/articles/phpinfo-version.png?w=640&amp;h=426&amp;s=212697a8a35e06c67f7171900410a11e" alt="Geladen ini-bestanden voor PHP in phpinfo()" loading="lazy" class="visibility-auto" title="Geladen ini-bestanden voor PHP in phpinfo()" srcset="https://aloia-systems.gumlet.io/images/articles/phpinfo-version.png?w=320&amp;h=213&amp;mode=crop&amp;crop=smart&amp;s=f7de2436a9a09ef0f3d4dc11d6f02ad5 320w,https://aloia-systems.gumlet.io/images/articles/phpinfo-version.png?w=480&amp;h=319&amp;mode=crop&amp;crop=smart&amp;s=709256e8d6909d3bb165451f9c78accb 480w,https://aloia-systems.gumlet.io/images/articles/phpinfo-version.png?w=640&amp;h=426&amp;mode=crop&amp;crop=smart&amp;s=7fcb3d873b5816854a0881fb4b95a31a 640w" sizes="(max-width: 360px) 320px, max-width: 640px) 480px, 640px"></p>
<p>Gewoonlijk wordt dit geladen vanuit <code>/etc/php/8.1/cli/conf.d/20-xdebug.ini</code>. Natuurlijk hangt het pad af van je PHP-versie en je besturingssysteem. In mijn geval draai ik PHP 8.1 op Ubuntu, dus dat van jou kan verschillen.</p>
<p>Zoek het pad naar je Xdebug-configuratie en open dit in een tekstedinaarr (of gedit, nano, vim) en verander de inhoud van dit bestand van:</p>
<pre><code class="language-conf">zend_extension=xdebug.so</code></pre>
<p>naar</p>
<pre><code class="language-conf">zend_extension=xdebug.so
xdebug.start_with_request=yes
xdebug.client_port=9003
xdebug.client_host=127.0.0.1
xdebug.mode=debug
xdebug.idekey=PHPSTORM</code></pre>
<p>Deze configuratie vertelt Xdebug om informatie naar poort 9003 op je lokale machine te sturen. Nu configureren we PHPStorm om een Xdebug-client op poort 9003 te starten.</p>
<h2>Stel PHPStorm in voor step debugging</h2>
<p>Nu we Xdebug 3 hebben geconfigureerd, moeten we PHPStorm configureren om debug informatie van Xdebug te ontvangen. We moeten een Xdebug Client binnen PHPStorm instellen. We kunnen dit configureren door naar de PHPStorm instellingen te gaan: <code>Ctrl + Alt + S</code>. Zoek in de zoekbalk naar <code>debug</code>. U ziet het volgende scherm:</p>
<p><img src="https://aloia-systems.gumlet.io/images/articles/xdebug-in-phpstorm.png?w=640&amp;h=426&amp;s=657553d639f1cd6349b2e26bcaf90fda" alt="Debug in PHPStorm" loading="lazy" class="visibility-auto" title="Debug in PHPStorm" srcset="https://aloia-systems.gumlet.io/images/articles/xdebug-in-phpstorm.png?w=320&amp;h=213&amp;mode=crop&amp;crop=smart&amp;s=a79712526167d8e83f0a5225a1be4f9a 320w,https://aloia-systems.gumlet.io/images/articles/xdebug-in-phpstorm.png?w=480&amp;h=319&amp;mode=crop&amp;crop=smart&amp;s=926f37fe2954d5cd72b06922494abb45 480w,https://aloia-systems.gumlet.io/images/articles/xdebug-in-phpstorm.png?w=640&amp;h=426&amp;mode=crop&amp;crop=smart&amp;s=39ee53308c1b52ecb1dc473aee0092f9 640w" sizes="(max-width: 360px) 320px, max-width: 640px) 480px, 640px"></p>
<p>In de Xdebug sectie moet u ervoor zorgen dat de <code>Debug port</code> op poort 9003 staat en dat de optie <code>Can accept external connection</code> is aangevinkt. Druk op "Toepassen" en "OK". Nu bent u klaar om uw stapsgewijze debuggen te testen!</p>
<h2>Test de step debugging met Xdebug 3 en PHPStorm</h2>
<p>Je hebt Xdebug 3 en PHPStorm geconfigureerd, dus nu is het tijd om je nieuwe debugging-mogelijkheden te testen! Start je PHP-ontwikkelingsserver (<code>php artisan serve</code> voor Laravel), plaats een breakpoint in je code, en <code>Start Listening for PHP Debug Connections</code>:</p>
<p><img src="https://aloia-systems.gumlet.io/images/articles/xdebug-start-listening.png?w=640&amp;h=426&amp;s=a1280e58fc35cf7ccef9e7e842fa4e16" alt="Start Listening for PHP Debug Connections" loading="lazy" class="visibility-auto" title="Start Listening for PHP Debug Connections" srcset="https://aloia-systems.gumlet.io/images/articles/xdebug-start-listening.png?w=320&amp;h=213&amp;mode=crop&amp;crop=smart&amp;s=270a880941758668534bf0c22e56f614 320w,https://aloia-systems.gumlet.io/images/articles/xdebug-start-listening.png?w=480&amp;h=319&amp;mode=crop&amp;crop=smart&amp;s=b2fde3246f1185db7ddea27737f4ed83 480w,https://aloia-systems.gumlet.io/images/articles/xdebug-start-listening.png?w=640&amp;h=426&amp;mode=crop&amp;crop=smart&amp;s=6257617d2b896bb36b92e4828a6aaff3 640w" sizes="(max-width: 360px) 320px, max-width: 640px) 480px, 640px"></p>
<p>Nadat je bent begonnen met luisteren, kun je naar je applicatie in de browser gaan en zou je een melding in PHPStorm moeten krijgen. Je zult het project moeten selecteren om de melding aan toe te wijzen, maar daarna krijg je mooie breakpoints in PHPStorm:</p>
<p><img src="https://aloia-systems.gumlet.io/images/articles/xdebug-step-debugger.png?w=640&amp;h=426&amp;s=7edf3005c1d42ab4d93c825017a4a0b4" alt="Step debugger in PHPStorm" loading="lazy" class="visibility-auto" title="Step debugger in PHPStorm" srcset="https://aloia-systems.gumlet.io/images/articles/xdebug-step-debugger.png?w=320&amp;h=213&amp;mode=crop&amp;crop=smart&amp;s=a22eae4234c51d2a6d7336b1d07dca29 320w,https://aloia-systems.gumlet.io/images/articles/xdebug-step-debugger.png?w=480&amp;h=319&amp;mode=crop&amp;crop=smart&amp;s=71aff8c9491f1932f38b3e74fa18ce52 480w,https://aloia-systems.gumlet.io/images/articles/xdebug-step-debugger.png?w=640&amp;h=426&amp;mode=crop&amp;crop=smart&amp;s=6447789693da0db6e3951fd0c7ee3fc3 640w" sizes="(max-width: 360px) 320px, max-width: 640px) 480px, 640px"></p>
<p>Je kunt nu breakpoints overal plaatsen en begonnen met debuggen van je PHP-applicaties als een programmeer ninja!</p>
<h2>Conclusie</h2>
<p>Met de hulp van Xdebug 3 en PHPStorm kun je nu je code als een pro debuggen. Je zult in staat zijn om met gemak eventuele problemen die kunnen ontstaan in je applicaties snel te identificeren. Met enkele eenvoudige stappen heb ik je laten zien hoe je stapsgewijs debuggen voor PHP kunt configureren, zodat je de tijd en energie kunt besparen bij het ontwikkelen van complexe projecten. Zolang je deze instructies volgt, hoef je maar enkele minuten te wachten voordat je geweldige resultaten begint te zien van het gebruik van dit krachtige toolset!</p></body></html>
]]></content>
                    <summary><![CDATA[Leer hoe je Xdebug en PHPStorm kunt configureren om stapsgewijs te debuggen met breakpoints in PHPStorm om je debugmogelijkheden te verbeteren. Optimaliseer je ontwikkelingstijd door deze eenvoudige tutorial te volgen!]]></summary>
                    <media:content xmlns:media="http://search.yahoo.com/mrss/" url="https://aloia-systems.gumlet.io/images/articles/xdebugging-in-phpstorm-cover.jpg?s=50663b0f6c0226185753cad17d933c9b" medium="image" type="image/jpeg" width="640" height="428" />
                  </entry>
<entry>
                    <title><![CDATA[Waarom je in 2023 (nog steeds) een RSS-feed moet toevoegen aan je website]]></title>
                    <link href="https://roelofjanelsinga.nl/articles/waarom-je-in-2023-een-rss-feed-moet-toevoegen-aan-je-website/"/>
                    <id>https://roelofjanelsinga.nl/articles/waarom-je-in-2023-een-rss-feed-moet-toevoegen-aan-je-website/</id>
                    <updated>2022-12-23T15:03:34+01:00</updated>
                    <published>2022-12-23T12:00:00+01:00</published>
                    <content type="html"><![CDATA[<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
<html><body><p><img src="https://aloia-systems.gumlet.io/images/articles/rss-logo.png?w=640&amp;h=426&amp;s=50691da752f73cbbb4009501c9211559" alt="RSS-logo" loading="lazy" class="visibility-auto" title="RSS-logo" srcset="https://aloia-systems.gumlet.io/images/articles/rss-logo.png?w=320&amp;h=213&amp;mode=crop&amp;crop=smart&amp;s=cbbc696d5241308294334291ec5db2f7 320w,https://aloia-systems.gumlet.io/images/articles/rss-logo.png?w=480&amp;h=319&amp;mode=crop&amp;crop=smart&amp;s=cbb5f47e8c22ad7239abe2daddeaa1d4 480w,https://aloia-systems.gumlet.io/images/articles/rss-logo.png?w=640&amp;h=426&amp;mode=crop&amp;crop=smart&amp;s=aa1a5162dda2885887177fd1e7ef5903 640w" sizes="(max-width: 360px) 320px, max-width: 640px) 480px, 640px"></p>
<h1>Waarom je in 2023 (nog steeds) een RSS-feed moet toevoegen aan je website</h1>
<p>Wil je een eenvoudige manier om op de hoogte te blijven van al het laatste nieuws en updates van je favoriete content websites? Nou, RSS feeds zijn er om je te helpen! Een RSS-feed (of Really Simple Syndication) is als een online krant die verhalen uit verschillende bronnen verzamelt. Het is een geweldige manier voor lezers om snel te weten te komen wat er nieuw is, zonder dat ze elke afzonderlijke website hoeven te bezoeken. En ook al lijkt het in 2022 verouderd, het toevoegen van een RSS-feed aan je inhoudelijke website kan in 2023 en daarna enorm voordelig zijn. In deze blogpost leg ik uit waarom je in deze tijd nog steeds een RSS feed aan je website zou moeten toevoegen.</p>
<p>Dit zijn de onderwerpen die we gaan bekijken:</p>
<ul>
<li>Wat is een RSS feed?</li>
<li>Hoe voeg ik een RSS feed toe aan mijn website?</li>
<li>Wat zijn de voordelen van het toevoegen van een RSS-feed aan een website?</li>
<li>Is het de moeite waard om in 2023 een RSS-feed toe te voegen?</li>
<li>Zijn er nadelen aan het gebruik van een RSS Feed voor websites?</li>
</ul>
<p>Laten we beginnen!</p>
<h2>Wat is een RSS feed?</h2>
<p>Heb je wel eens gehoord van een RSS feed? Het staat voor "Really Simple Syndication" en het is een geweldige manier om het laatste nieuws en updates van meerdere bronnen te krijgen, zonder dat je naar elke website afzonderlijk hoeft te gaan. Een RSS-feed is een op XML gebaseerd bestand (een "feed" genoemd) dat alle recente inhoud van je website bevat. Mensen kunnen zich op de feed abonneren, zodat hun favoriete nieuwslezer automatisch wordt bijgewerkt als er nieuwe inhoud wordt gepubliceerd.</p>
<p>Begin jaren 2000 werd RSS ontwikkeld door Netscape Communications Corporation als alternatief voor andere formaten voor websyndicatie. Deze versie - die toen RSS 0.91 heette - werd snel populair bij uitgevers van inhoud.</p>
<p>Een paar jaar later verbeterden software-ontwikkelaars het formaat verder tot wat we nu RSS 2.0 noemen. Deze versie had meer controle over hoe informatie werd weergegeven aan nieuwslezers, en het werd nog populairder vanwege zijn flexibele karakter en gebruiksgemak in vergelijking met andere web-syndicatie formaten.</p>
<p>Tegenwoordig gebruiken mensen RSS-feeds voor blogs, nieuwssites, podcasts en meer - zodat we allemaal op de hoogte blijven van de nieuwste inhoud van onze favoriete bronnen!</p>
<h2>Hoe voeg ik een RSS feed toe aan mijn website?</h2>
<p>Het toevoegen van een RSS-feed aan je website is vrij eenvoudig. Als je een CMS gebruikt om je website te onderhouden, is de kans groot dat je al een RSS-feed op je website hebt. Je kunt dit controleren door naar <code>mywebsite.com/rss.xml</code> te gaan. Als je een XML document ziet, heb je al een RSS feed op je website en kun je naar de volgende paragraaf gaan.</p>
<p>Als je nog geen RSS-feed hebt, is het aanmaken ervan vrij eenvoudig. Laten we een basisvoorbeeld bekijken:</p>
<pre><code class="language-xml">&lt;?xml version="1.0" encoding="utf-8"?&gt;
&lt;rss xmlns:dc="http://purl.org/dc/elements/1.1/" version="2.0"&gt;
    &lt;channel&gt;
        &lt;description&gt;My website name&lt;/description&gt;
        &lt;title&gt;My website name&lt;/title&gt;
        &lt;link&gt;https://mywebsite.com&lt;/link&gt;
        &lt;pubDate&gt;Fri, 23 Dec 2022 12:00:00 GMT&lt;/pubDate&gt;
        &lt;item&gt;
            &lt;description&gt;This is a description of my blog post.&lt;/description&gt;
            &lt;title&gt;The title of my blog post&lt;/title&gt;
            &lt;link&gt;https://mywebsite.com/blog/my-great-post/&lt;/link&gt; &lt;guid&gt;https://mywebsite.com/blog/my-great-post/&lt;/guid&gt;
            &lt;pubDate&gt;Fri, 23 Dec 2022 12:00:00 GMT&lt;/pubDate&gt;
            &lt;media:content xmlns:media="http://search.yahoo.com/mrss/" url="https://mywebsite.com/image.jpg" medium="image" type="image/jpeg" width="640" height="426"/&gt;
        &lt;/item&gt;
    &lt;/channel&gt;
&lt;/rss&gt;</code></pre>
<p>Elke RSS feed begint met een XML versie verklaring, heeft een RSS wrapper, en bevat kanaal en item informatie.</p>
<p>Het kanaal bevat informatie over je website: titel, beschrijving, URL (link), en de publicatiedatum van deze feed (pubDate). De items bevatten soortgelijke items: titel, beschrijving, URL (link), pubDate, en een mediaobject.</p>
<p>Er zijn nog veel meer mogelijkheden, maar dit zijn de basisprincipes van een RSS feed voor een blog.</p>
<p>Je kunt de volledige RSS 2.0 spec vinden op <a href="https://validator.w3.org/feed/docs/rss2.html">W3C</a>.</p>
<h2>Wat zijn de voordelen van het toevoegen van een RSS-feed aan een website?</h2>
<p>Het toevoegen van een RSS-feed aan je website kan in 2023 en daarna enorm voordelig zijn. Hier zijn enkele van de grootste voordelen:</p>
<ul>
<li>
<p><strong>Verhoogde zichtbaarheid</strong>: Door een RSS-feed aan te bieden, maak je het makkelijker voor gebruikers om nieuwe inhoud op je website te vinden zonder elke pagina handmatig te hoeven bezoeken. Dit maakt het voor hen gemakkelijker om op de hoogte te blijven van je laatste berichten en updates.</p>
</li>
<li>
<p><strong>Verbeterde vindbaarheid</strong>: Met RSS-feeds kan inhoud worden gesyndiceerd over verschillende platforms, wat je zichtbaarheid in de zoekresultaten kan helpen vergroten en organisch verkeer naar je website kan stimuleren.</p>
</li>
<li>
<p><strong>Hogere betrokkenheid</strong>: Door een RSS-feed aan te bieden, maak je het makkelijker voor gebruikers om betrokken te blijven bij je inhoud. Daardoor kun je de tijd die gebruikers op je website doorbrengen verlengen, wat kan leiden tot hogere conversiepercentages en een betere algemene gebruikerservaring.</p>
</li>
<li>
<p><strong>Makkelijker inhoud promoten</strong>: Met RSS feeds kun je gemakkelijker je inhoud promoten via sociale media sites als Twitter, Facebook en LinkedIn. Het stelt je ook in staat om automatisering in te bouwen op nieuwe items in je RSS feed. Dit bericht wordt bijvoorbeeld automatisch gepubliceerd op LinkedIn en Twitter, omdat de RSS-feed is bijgewerkt met dit blogbericht.</p>
</li>
</ul>
<p>Kortom, het toevoegen van een RSS-feed aan je website in 2023 kan je helpen je zichtbaarheid, betrokkenheid en algehele gebruikerservaring te vergroten. Wacht dus niet langer - begin vandaag nog met het opzetten van je RSS feed!</p>
<h2>Is het de moeite waard om in 2023 een RSS-feed toe te voegen?</h2>
<p>RSS was vroeger de beste manier om je inhoud de wereld in te krijgen. Sociale media namen dit voordeel weg omdat de inhoud ervan veel gemakkelijker te verteren was dan het opzetten van een RSS feed. Maar nu er meer ongelooflijke (no-code) tools zijn dan ooit, komt de rol van de RSS feed terug!</p>
<p>RSS feeds kunnen worden gebruikt voor meer dan alleen content promotie. Ze kunnen worden gebruikt om het publiceren van inhoud op verschillende platforms te automatiseren, waardoor je het meeste uit je inhoud kunt halen en een breder publiek kunt bereiken. Je kunt je blogberichten automatisch cross-posten naar veel platforms tegelijk, je kunt je e-commerce aanbod synchroniseren naar Google shopping, je Facebook productcatalogus en Instagram shopping. Het mooiste is dat je voor deze automatisering geen API-toegang hoeft in te stellen! Alles wat je nodig hebt is je vertrouwde RSS-feed.</p>
<p>Al met al zal het toevoegen van een RSS-feed aan je website in 2023 ongetwijfeld veel voordelen opleveren en je helpen een succesvolle online aanwezigheid op te bouwen.</p>
<h2>Zijn er nadelen aan het gebruik van een RSS Feed voor websites?</h2>
<p>Zoals elke technologie hebben ook RSS feeds bepaalde nadelen. Het grootste is dat de meeste gebruikers tegenwoordig geen RSS-lezers gebruiken. Je zult dus moeten vertrouwen op andere methoden (zoals e-mail nieuwsbrieven) om je volgers op de hoogte te brengen van nieuwe inhoud en updates. Bovendien, als je een blog of een e-commerce site hebt, moet je ervoor zorgen dat je RSS feed up-to-date is met de nieuwste inhoud. Als het verouderd is, kan het een afknapper zijn voor bezoekers en zullen ze je website niet bezoeken.</p>
<p>Over het geheel genomen kan een RSS-feed enorm voordelig zijn als je hem zorgvuldig gebruikt en actueel houdt. Je kunt deze technologie het beste gebruiken in combinatie met andere methoden zoals e-mailnieuwsbrieven, berichten op sociale media en blogs om het meeste uit je inhoud te halen.</p>
<h2>Conclusie</h2>
<p>Het toevoegen van een RSS-feed aan je website in 2023 kan tal van voordelen opleveren, zoals het vergroten van de zichtbaarheid, de vindbaarheid en de betrokkenheid. Je moet er echter voor zorgen dat je RSS-feed altijd actueel is om er het meeste uit te halen. Bovendien moet je andere methoden gebruiken, zoals e-mailnieuwsbrieven en berichten op sociale media in combinatie met je RSS feed om de beste resultaten te bereiken.</p>
<p>Over het geheel genomen kan een RSS feed, mits goed gebruikt, een geweldig hulpmiddel zijn om de online aanwezigheid van je website te vergroten en meer mensen te bereiken met je inhoud. Wacht dus niet langer - begin vandaag nog met het opzetten van je RSS feed!</p></body></html>
]]></content>
                    <summary><![CDATA[Voeg in 2023 een RSS-feed toe aan je website om de zichtbaarheid, vindbaarheid en betrokkenheid te vergroten. Automatiseer het publiceren van inhoud op verschillende platforms zonder API-toegang. Haal vandaag nog het meeste uit je inhoud!]]></summary>
                    <media:content xmlns:media="http://search.yahoo.com/mrss/" url="https://aloia-systems.gumlet.io/images/articles/rss-logo.png?s=19cb49476a0c10024462f170a93ab361" medium="image" type="image/jpeg" width="640" height="428" />
                  </entry>
<entry>
                    <title><![CDATA[Waarom Caddy misschien wel de beste start is voor je volgende softwareproject]]></title>
                    <link href="https://roelofjanelsinga.nl/articles/waarom-caddy-misschien-wel-de-beste-start-is-voor-je-volgende-softwareproject/"/>
                    <id>https://roelofjanelsinga.nl/articles/waarom-caddy-misschien-wel-de-beste-start-is-voor-je-volgende-softwareproject/</id>
                    <updated>2022-10-22T17:21:54+02:00</updated>
                    <published>2022-10-22T12:00:00+02:00</published>
                    <content type="html"><![CDATA[<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
<html><body><p><img src="https://aloia-systems.gumlet.io/images/articles/caddy.png?w=640&amp;h=426&amp;s=617aae294a483f5ea4d3b8b3c9e885c3" alt="Caddy logo" loading="lazy" class="visibility-auto" title="Caddy logo" srcset="https://aloia-systems.gumlet.io/images/articles/caddy.png?w=320&amp;h=213&amp;mode=crop&amp;crop=smart&amp;s=98caab053e5dbcb24a1b907ad0b14f51 320w,https://aloia-systems.gumlet.io/images/articles/caddy.png?w=480&amp;h=319&amp;mode=crop&amp;crop=smart&amp;s=eaf4398b1c06c41b6aa577a79ba6c236 480w,https://aloia-systems.gumlet.io/images/articles/caddy.png?w=640&amp;h=426&amp;mode=crop&amp;crop=smart&amp;s=830f9a9ac138fc253e29a02b4b8a60a0 640w" sizes="(max-width: 360px) 320px, max-width: 640px) 480px, 640px"></p>
<h1>Waarom Caddy misschien wel de beste start is voor je volgende softwareproject</h1>
<p>Vind je het vreselijk om een webserver op te zetten voor je project(en) en zou je willen dat je dat helemaal kon overslaan en dat het dan nog steeds magisch werkt? Dan is Caddy misschien wel de perfecte webserver voor je volgende project!</p>
<p>In deze blog gaan we kijken naar een paar van de voordelen van Caddy die het voor mij meteen verkochten als de vervanger van Nginx en Apache. Dit zijn de onderwerpen die we gaan bekijken:</p>
<ol>
<li>Wat is Caddy?</li>
<li>Hoe verhoudt Caddy zich tot andere webservers?</li>
<li>Waarom zou je Caddy gebruiken voor je volgende softwareproject?</li>
<li>Hoe begin je met Caddy?</li>
</ol>
<p>Laten we er meteen in duiken en zien waar Caddy voor staat!</p>
<h2>Wat is Caddy?</h2>
<p>Caddy is een webserver, zoals Nginx en Apache, die verkeer van het internet naar je applicatie of statische bestanden geleid of als reverse proxy fungeert.</p>
<p>Maar het is zoveel meer dan alleen een webserver, het genereert ook automatisch SSL certificaten voor je website, zorgt voor caching, en de configuratie is hysterisch eenvoudig vergeleken met Nginx &amp; Apache.</p>
<p>Caddy zorgt voor de dingen die je niet graag doet in projecten met Nginx en Apache. Zeker, het is niet moeilijk om SSL in te stellen voor die webservers, maar het is toch iets waar je over na moet denken. Caddy doet al dit werk voor je, dus je hoeft het alleen maar naar je applicatie te wijzen en het werkt gewoon.</p>
<p>Het Caddy-team heeft een uitstekende illustratie samengesteld van wat Caddy in technische termen is:</p>
<p><img src="https://aloia-systems.gumlet.io/images/articles/caddy-moving-parts.svg?w=640&amp;h=426&amp;s=a31ce2667432fd92679f2ce119ecdff6" alt="Bewegende onderdelen in Caddy" loading="lazy" class="visibility-auto" title="Bewegende onderdelen in Caddy" srcset="https://aloia-systems.gumlet.io/images/articles/caddy-moving-parts.svg?w=320&amp;h=213&amp;mode=crop&amp;crop=smart&amp;s=2b5f28dbfce9a3c938ec77a078a6b0ee 320w,https://aloia-systems.gumlet.io/images/articles/caddy-moving-parts.svg?w=480&amp;h=319&amp;mode=crop&amp;crop=smart&amp;s=007f7a4a673c723ceebcffcb14b3f6a1 480w,https://aloia-systems.gumlet.io/images/articles/caddy-moving-parts.svg?w=640&amp;h=426&amp;mode=crop&amp;crop=smart&amp;s=22a1e23647feeb27655ca6bd2009adbc 640w" sizes="(max-width: 360px) 320px, max-width: 640px) 480px, 640px"></p>
<h2>Hoe verhoudt Caddy zich tot andere webservers?</h2>
<p>Ik denk dat het belangrijkste om naar te kijken voor de meeste ontwikkelaars de snelheid zal zijn. Hoe snel is het vergeleken met de andere webservers? Er zijn veel benchmarks op het internet te vinden die Caddy vergelijken met Nginx, bijvoorbeeld <a href="https://blog.tjll.net/reverse-proxy-hot-dog-eating-contest-caddy-vs-nginx/">35 Million Hot Dogs: Benchmarking Caddy vs. Nginx</a>. Deze benchmark laat iets heel interessants zien:</p>
<ul>
<li>Nginx is marginaal sneller dan Caddy in het afhandelen van verzoeken</li>
<li>Caddy is multi-threaded en zal latency gaan gebruiken wanneer het wordt bestookt door enorme aantallen HTTP verzoeken...maar het zal alle aanvragen altijd goed afhandelen</li>
<li>Nginx is single-threaded (in deze test) en zal verbindingen gaan weigeren zodra het aan zijn capaciteit zit</li>
<li>Nginx presteert alleen beter dan Caddy met een speciale prestatie-geoptimaliseerde configuratie, terwijl Caddy bij een "standaard" configuratie blijft.</li>
</ul>
<p>Het lezen van die benchmark is je tijd waard als je meer wilt weten over de prestatievergelijking.</p>
<p>Ik heb helaas geen goede benchmark kunnen vinden die ook Apache omvat. Als ik er toevallig eentje vind, zal ik dit bijwerken en een link naar de vergelijking plaatsen.</p>
<p>Dus als je kijkt naar de prestaties van Caddy vergeleken met andere beschikbare webservers, dan zien we dat hij niet alleen vergelijkbaar is met Nginx, maar het soms zelfs overtreft. De grootste takeaway van het lezen van die benchmark is het feit dat Caddy zo snel is met de standaardinstellingen. Je hoeft geen tijd te besteden aan het optimaliseren van je configuratie om uitstekende snelheden te krijgen zoals je met Nginx zou moeten doen. Dit is wat ik wil! Ik wil dat de webserver gewoon werkt en me niet in de weg zit. Caddy voldoet hierin voor mij!</p>
<h2>Waarom zou je Caddy gebruiken voor je volgende softwareproject?</h2>
<p>Ik heb al een paar redenen genoemd waarom je Caddy zou moeten gebruiken voor je volgende softwareproject, maar laten we ze nog eens opnoemen:</p>
<ul>
<li>Het is vergelijkbaar, zo niet sneller, dan Nginx</li>
<li>De configuratie ervan is ongelooflijk eenvoudig</li>
<li>Je hoeft niet na te denken over SSL-certificaten</li>
<li>Het is multi-threaded, dus het maakt echt gebruik van de server waarop je het draait</li>
</ul>
<p>Laten we een paar uitstekende voordelen toevoegen aan het gebruik van Caddy voor je volgende project!</p>
<p>Ten eerste heeft Caddy geen dependencies. Het is een gecompileerde Go binary die overal kan draaien. Dit maakt het ideaal voor gebruik in een container in je Docker of Kubernetes omgeving.</p>
<p>Ten tweede biedt het dingen als load-balancing van het verkeer naar backend diensten, gezondheidscontroles, circuit breaking en caching out-of-the-box. Voor mij is dit een duidelijk voordeel, omdat dit veel tijd bespaart. Tijd die je kunt besteden aan het bouwen van je applicatie.</p>
<p>Tenslotte is het grootste voordeel van het gebruik van Caddy dat het ingebouwde directives heeft voor het gebruik van fastcgi. Dit helpt je om verkeer naar je PHP applicatie te leiden met een enkele regel in je configuratiebestand.</p>
<p>Maar hoe begin je met Caddy? Laten we dat eens uitzoeken!</p>
<h2>Hoe begin je met Caddy?</h2>
<p>Aan de slag gaan met Caddy is eenvoudig! Je kunt de CLI gebruiken om je configuratie te serveren en meteen een server te starten, of je kunt Docker gebruiken. Ik gebruik liever Docker omdat het perfect past in dit soort projecten van mij.</p>
<p>Laten we eens kijken naar de configuratie om verkeer naar onze PHP/Laravel applicatie te sturen:</p>
<pre><code>(laravel) {
    root * /var/www/html/public
    encode zstd gzip
    file_server
}

(redirect_clean_url) {
    handle_path /index.php* {
        redir {uri} permanent
    }
}

:8000 {
    import laravel
    import redirect_clean_url

    handle {
        try_files {path} {path}/ /index.php?{query}
        php_fastcgi my_php_fpm_backend:9000
    }
}</code></pre>
<p>Het codeblok dat begint met (laravel) en (redirect_clean_url) zijn snippets, in wezen herbruikbare blokken configuratie die je op elke plek kunt toepassen door ze te importeren: "import laravel" en "import redirect_clean_url". Als je eerder een Laravel applicatie hebt gehost, dan weet je dat je al het verkeer moet leiden naar het bestand index.php in de publieke map van je project. De "laravel" snippet stelt de document route in naar die publieke map, schakelt gzip en zstd encoding in, en vertelt Caddy om statische bestanden uit de publieke map te serveren (afbeeldingen, css bestanden, enz.).</p>
<p>De redirect_clean_url snippet is een belangrijke snippet om de SEO van je applicatie te verbeteren. Al het verkeer omleiden naar je index.php bestand is geweldig, maar het veroorzaakt ook een probleem: zowel <a href="https://example.com">https://example.com</a> als <a href="https://example.com/index.php">https://example.com/index.php</a> zijn geldige paden. Dit veroorzaakt lelijke URL's (<a href="https://example.com/index.php/blog">https://example.com/index.php/blog</a> bijvoorbeeld) en Google zou dit kunnen markeren als duplicate content. Om dit alles te voorkomen willen we al het verkeer van /index.php omleiden naar een schone URL zonder index.php erin. Deze snippet zorgt ervoor dat /index.php/blog wordt omgeleid naar /blog. Het doet dit met een 301: let op het sleutelwoord "permanent".</p>
<p>Het codeblok ":8000" is onze daadwerkelijke website, in dit geval localhost:8000. Je kunt dit ook vervangen door example.com en dan worden automatisch SSL-certificaten voor je domein gegenereerd en via HTTPS aangeboden. In het handle code blok vertellen we Caddy eerst te zoeken naar statische bestanden en als het die niet kan vinden, het verkeer om te leiden naar de index.php in de publieke map. Als het verkeer wordt omgeleid naar PHP, kun je het FPM backend specificeren met de "php_fastcgi" directive. In mijn geval routeert dit het verkeer naar een PHP-FPM container in dezelfde docker omgeving, maar dit kan ook <a href="http://127.0.0.1:9000">http://127.0.0.1:9000</a> zijn of een andere plaats waar je je FPM server draait.</p>
<p>Nu heb je een volledig functionele webserver voor je PHP applicatie, inclusief een SSL certificaat. Dat is eigenlijk alles. Je bent klaar. Zo eenvoudig is het.</p>
<p>De eenvoud van dit configuratiebestand, de uitstekende prestaties van de webserver en de fantastische [documentatie] (<a href="https://caddyserver.com/docs/">https://caddyserver.com/docs/</a>) maken Caddy tot mijn favoriete webserver.</p>
<h2>Conclusie</h2>
<p>Caddy is om verschillende redenen een uitstekende webserver: het is qua snelheid vergelijkbaar met Nginx, de configuratie is veel eenvoudiger, en je hoeft niet na te denken over SSL-certificaten. Het neemt al het vervelende werk weg bij het instellen van een webserver en helpt je weer verder met het ontwikkelen van je applicatie of website! Als je op zoek bent naar een nieuwe webserver voor je volgende project, kijk dan niet verder dan Caddy.</p></body></html>
]]></content>
                    <summary><![CDATA[Vind je het vreselijk om een webserver op te zetten voor je project(en) en zou je willen dat je dat helemaal kon overslaan en dat het dan nog steeds magisch werkt? Dan is Caddy misschien wel de perfecte webserver voor je volgende project!
]]></summary>
                    <media:content xmlns:media="http://search.yahoo.com/mrss/" url="https://aloia-systems.gumlet.io/images/articles/caddy.png?s=e4651dbd12770a415cbb06806aeadcfc" medium="image" type="image/jpeg" width="640" height="428" />
                  </entry>
<entry>
                    <title><![CDATA[Hoe migreer je van Mailchimp naar Postmark + Temporal]]></title>
                    <link href="https://roelofjanelsinga.nl/articles/hoe-migreer-je-van-mailchimp-naar-postmark-temporal/"/>
                    <id>https://roelofjanelsinga.nl/articles/hoe-migreer-je-van-mailchimp-naar-postmark-temporal/</id>
                    <updated>2022-03-04T12:04:14+01:00</updated>
                    <published>2022-03-04T12:00:00+01:00</published>
                    <content type="html"><![CDATA[<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
<html><body><p><img src="https://aloia-systems.gumlet.io/images/articles/send-a-mail.jpg?w=640&amp;h=426&amp;s=abe70eb7f5eb9db178a18e431e1de73d" alt="Stuur een mail op een typemachine" loading="lazy" class="visibility-auto" title="Stuur een mail op een typemachine" srcset="https://aloia-systems.gumlet.io/images/articles/send-a-mail.jpg?w=320&amp;h=213&amp;mode=crop&amp;crop=smart&amp;s=c65a190548fd047f85ea512a85afb1ea 320w,https://aloia-systems.gumlet.io/images/articles/send-a-mail.jpg?w=480&amp;h=319&amp;mode=crop&amp;crop=smart&amp;s=8548fba17def14ab17a2321f001e07d4 480w,https://aloia-systems.gumlet.io/images/articles/send-a-mail.jpg?w=640&amp;h=426&amp;mode=crop&amp;crop=smart&amp;s=9c220ac648991f4aa752bb555a701e51 640w" sizes="(max-width: 360px) 320px, max-width: 640px) 480px, 640px">
<span class="caption">Foto door <a href="https://unsplash.com/@markuswinkler" rel="nofollow">Markus Winkler</a></span></p>
<h1>Hoe migreer je van Mailchimp naar Postmark + Temporal</h1>
<p>MailChimp is een geweldig SaaS platform om e-mails naar je abonnees te sturen en met automatisering te werken om aan je mailinglijst te verkopen.
Maar als je eenmaal een omvangrijk publiek hebt en je e-mail interacties wilt aanpassen, krijg je te maken met een fors prijskaartje.
Mailchimp is erg duur!
Als je een mailinglijst hebt van 2000 contacten en je zit op het goedkoopste betaalde plan, dan betaal je al $34 per maand.
Dit is een prima optie voor een marketing team dat geen toegang heeft tot een software ontwikkelaar, maar ik ben zo'n software ontwikkelaar.</p>
<p>Voor we met de migratie beginnen, stellen we de 2 helden van het verhaal voor: Postmark en Temporal.
Als je nog niet eerder van deze twee gehoord hebt, volgt hier een korte introductie.
Als je ze al wel kent, kun je dit overslaan en naar de delen gaan die je wilt lezen:</p>
<ol>
<li><a href="#postmark">Wat is Postmark?</a></li>
<li><a href="#temporal">Wat is Temporal?</a></li>
<li><a href="#templates">Maak e-mail sjablonen in Postmark</a></li>
<li><a href="#temporal-workflows">Maak Temporele werkstromen</a>
<ol>
<li><a href="#nieuwsbrief">De nieuwsbrief verstuur-workflow</a></li>
<li><a href="#afmeldingen">Behandel afmeldingen voor de nieuwsbrief</a></li>
</ol></li>
</ol>
<h3 id="postmark">Wat is Postmark?</h3>
<p><img src="https://aloia-systems.gumlet.io/images/articles/postmark-homepage.png?w=640&amp;h=426&amp;s=09ec4009f2a16efa5b6514edebd97caf" alt="Postmark homepage" loading="lazy" class="visibility-auto" title="Postmark homepage" srcset="https://aloia-systems.gumlet.io/images/articles/postmark-homepage.png?w=320&amp;h=213&amp;mode=crop&amp;crop=smart&amp;s=531aba54189c5567fbc8cbac17c05e38 320w,https://aloia-systems.gumlet.io/images/articles/postmark-homepage.png?w=480&amp;h=319&amp;mode=crop&amp;crop=smart&amp;s=920f8c5b613fe8e47d8f6737d9a74cc0 480w,https://aloia-systems.gumlet.io/images/articles/postmark-homepage.png?w=640&amp;h=426&amp;mode=crop&amp;crop=smart&amp;s=b9717edba8dd8cfd57b36f073dfedb65 640w" sizes="(max-width: 360px) 320px, max-width: 640px) 480px, 640px"></p>
<p>Misschien heb je al eens van Postmark gehoord, het is een vrij bekend e-mail platform waarmee je transactionele- en marketing e-mails kunt versturen en zelfs inkomende e-mails kunt afhandelen.
In mijn ervaring is het leveringspercentage beter dan dat van een paar andere opties die er zijn.
Een van de grootste voordelen is het feit dat je <a href="https://github.com/wildbit/mailmason">templates in code</a> kunt maken en die met Postmark kunt synchroniseren.
Dit is een heel belangrijk aspect voor dit hele proces, want hiermee kan ik e-mails versturen met behulp van een REST API.</p>
<h3 id="temporal">Wat is Temporal?</h3>
<p><img src="https://aloia-systems.gumlet.io/images/articles/temporal-homepage.png?w=640&amp;h=426&amp;s=6d9724c4c96631b3d8b4765342ee8283" alt="Temporal homepage" loading="lazy" class="visibility-auto" title="Temporal homepage" srcset="https://aloia-systems.gumlet.io/images/articles/temporal-homepage.png?w=320&amp;h=213&amp;mode=crop&amp;crop=smart&amp;s=2f7d059a5b597f85993443ddf67e9fe3 320w,https://aloia-systems.gumlet.io/images/articles/temporal-homepage.png?w=480&amp;h=319&amp;mode=crop&amp;crop=smart&amp;s=d82b51ef9e097500e96a659eb7ef8eca 480w,https://aloia-systems.gumlet.io/images/articles/temporal-homepage.png?w=640&amp;h=426&amp;mode=crop&amp;crop=smart&amp;s=b22085acd2bf5f37724321d7a62bd2c5 640w" sizes="(max-width: 360px) 320px, max-width: 640px) 480px, 640px"></p>
<p>Het tweede stukje software dat dit alles mogelijk maakt is <a href="https://temporal.io">Temporal</a>.
Temporal is software die de state van je code bijhoudt.
Eenvoudig gezegd voert het elke regel code slechts eenmaal uit en kan het de uitvoering van code hervatten na een systeemcrash.
Dit maakt je code ongelooflijk stabiel.
Als dat je nog niet overtuigd heeft van de kracht ervan, kan het volgende voorbeeld het misschien verduidelijken.</p>
<blockquote>
<p><strong>Voorbeeld</strong></p>
<p>Als je een bankprogramma hebt en je klant stuurt een betaling naar een andere klant en je programma crasht halverwege: wat gebeurde er met de betaling?
Wat gebeurt er als je de applicatie opnieuw start?
Zal dit proces 2 keer geld van je klant afschrijven?
Temporal weet waar de applicatie was in zijn code-uitvoering en hervat vanaf die exacte regel.
Temporal helpt je om je klant nooit twee keer te laten betalen, zelfs niet tijdens een crash.</p>
</blockquote>
<h4>Laat je code weken wachten</h4>
<p>Een ander groot voordeel van Temporal is dat je processen weken of maanden kunt laten wachten als je dat wilt.
In normale code kun je een soort vertraging (sleep, time.Sleep, enz.) in je code zetten, maar je zou er niet aan denken om dit voor 14 dagen te doen.
Meestal zou je je code maar met ongeveer 10 seconden vertragen.</p>
<p>Maar waarom is dit belangrijk?
Dit is belangrijk, want het vereenvoudigt je code drastisch.
Een klant voor een abonnement laten betalen is nu gewoon een for-loop met een vertraging van 30 dagen na de betaling.
Controleer 30 dagen later of de klant nog geabonneerd is, reken af, en wacht nog eens 30 dagen.
Het is echt zo eenvoudig.
Houd dit in je achterhoofd, want dit zal heel belangrijk worden bij dit inplannen van e-mails om naar je contacten te sturen.</p>
<p>Nog een laatste ding om te benadrukken voor we kunnen beginnen!
Je kunt de uitvoering van code plannen op basis van een cron schema.
Dit wordt het hart van de nieuwsbrief applicatie.
Genoeg gepraat, laten we aan wat code beginnen!</p>
<h2 id="templates">Maak e-mail templates in Postmark</h2>
<p>Als je ooit e-mails vanuit je code gestuurd hebt, heb je misschien met lokale templates gewerkt en kant-en-klare HTML e-mails naar je contacten gestuurd.
Dit is altijd een pijnpunt en ik kan niet eens beginnen te tellen hoe vaak een e-mail er op een mobiel toestel net niet goed uitziet of er op Gmail in Safari een beetje naast zit.
Het maken van e-mails in HTML brengt je gewoon terug naar de "Good ol' HTML 4 dagen" waarin alles een tabel is en niets responsief is.
Laten we niet eens proberen dit te doen en laat Postmark dit voor je afhandelen.</p>
<p>Als je de <a href="https://github.com/wildbit/mailmason">mailmason</a> starter gebruikt die ik ook als basis heb gebruikt, zie je minimale HTML tabellen en meestal alleen eenvoudige HTML templates.
Je kunt je e-mails stijlen met eenvoudige CSS bestanden en Mailmason genereert zelfs de platte tekst versies van je e-mails.</p>
<p>Nadat je je templates met je Postmark server gesynchroniseerd hebt, heb je templates met gemakkelijk te gebruiken aliassen.
Je kunt deze template aliassen gebruiken, naast de variabelen die je voor je templates nodig hebt (voornaam, enz.) en ze als JSON naar Postmark sturen om je e-mail te versturen.
E-mails versturen met een eenvoudige REST API aanroep is een fantastisch gevoel.</p>
<p>Laten we ons ten behoeve van deze post voorstellen dat we een template als dit gebruiken:</p>
<pre><code class="language-html">&lt;h1&gt;Hallo!&lt;/h1&gt;
&lt;p&gt;
    Ik hoop dat je een fijne week hebt gehad! Dit is wat ik deze week voor je geschreven heb, ik hoop dat je ervan geniet!
&lt;/p&gt;

&lt;img src="{{image_url}}" &gt;

&lt;br /&gt;

&lt;h1&gt;{{title}}&lt;/h1&gt;

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

&lt;a href="{{url}}" class="cta-button"&gt;Lees &amp;quot;{{title}}&amp;quot;&lt;/a&gt;

&lt;p&gt;
    Ik kijk ernaar uit je binnenkort de volgende e-mail te sturen, doei!
&lt;/p&gt;</code></pre>
<p>Zoals je ziet, hebben we een paar variabelen die we kunnen invullen met de REST API:</p>
<ul>
<li>image_url</li>
<li>title</li>
<li>description</li>
<li>url</li>
</ul>
<p>Laten we deze template het alias <strong>"weekly-newsletter"</strong> geven.</p>
<p>Dit is een heel eenvoudige e-mail template met minimale styling dat op de Postmark servers wordt opgeslagen, in plaats van in je eigen applicatie.</p>
<p>Als je ge&iuml;nteresseerd bent in meer informatie over mailmason en mijn automatische proces om templates met Postmark te synchroniseren, neem dan contact met me op. </p>
<p>Laten we overgaan tot het hart van de automatisering: Temporal.</p>
<h2 id="temporal-workflows">Maak Temporal-workflows</h2>
<p>Temporal, de state machine, heeft een concept dat workflows heet.
Een workflow is een verzameling afzonderlijke stappen die een (meer ingewikkelde) taak uitvoeren.
Een workflow moet deterministisch zijn, wat betekent dat het telkens hetzelfde resultaat heeft als het uitgevoerd wordt met dezelfde input.</p>
<p>Elk niet-deterministisch gedrag moet naar een activity verplaatst worden, want het resultaat van een activity wordt in de geschiedenis van de workflow vastgelegd.
Je kunt een activity interpreteren als een stap in je workflow.
Enkele voorbeelden van code die goed is voor een activity is: een e-mail sturen of iets ophalen uit een API.</p>
<p>Als we dit opsplitsen voor het versturen van een nieuwsbrief, kun je een workflow zien als deze stappen:</p>
<ol>
<li>Naar wie stuur ik een e-mail?</li>
<li>Is er iets voor mij om te sturen? Zo nee, kijk dan volgende week nog eens.</li>
<li>Zeg Postmark dat het contact X template Y met variabelen Z moet sturen</li>
<li>Klaar, controleer volgende week opnieuw</li>
</ol>
<p>Tijdens deze workflow wil ik de code zo snel mogelijk overslaan en volgende week opnieuw controleren.
"Volgende week weer controleren" belicht een van de mogelijkheden die Temporal biedt voor workflows: Cronjob workflows.
Deze Cronjob workflows kunnen uitgevoerd worden wanneer je maar wilt, in mijn geval elke zaterdag om 15:00 (15 uur).
Dit cron schema ziet er als volgt uit: <a href="https://crontab.guru/#0_15_*_*_6">"0 15 * * 6"</a>.</p>
<p>Het starten (inplannen) van een workflow in mijn code, die in Go geschreven is, ziet er als volgt uit:</p>
<pre><code class="language-go">// Maak een eenvoudig te gebruiken workflow ID
const WorkflowID = "nieuwsbrief-%s"

// Registreer de workflow met een makkelijke naam
w.RegisterWorkflowWithOptions(EmailNewsletterWorkflow, workflow.RegisterOptions{
    Name: "email.nieuwsbrief",
})

type SubscribeRequest struct {
    Email string `json: "email"`
}

// Voer de workflow uit met een cron schema
als _, err := s.client.ExecuteWorkflow(ctx, client.StartWorkflowOptions{
    ID: fmt.Sprintf(WorkflowID, "hello@example.com"),
    TaskQueue: Queue,
    CronSchedule: "0 15 * * 6",
}, "email.nieuwsbrief", SubscribeRequest{
    Email: "hello@example.com",
}); err != nil {
    return err
}</code></pre>
<p>Er is veel code die ik in dit voorbeeld weglaat, zoals het opzetten van een Temporal worker en het instellen van de Temporal client.
Om het eenvoudig te houden hardcode ik in dit voorbeeld ook het e-mail adres.
De invoergegevens voor de workflow, "SubscribeRequest", hebben json tags, omdat temporal deze invoergegevens in de database opslaat en door de keys die het moet gebruiken als json te specificeren, vermijd je enkele zeldzame codeer- en decodeerproblemen.</p>
<h4>Het workflow ID</h4>
<p>Ik leg de nadruk op het gemakkelijk te gebruiken Workflow ID, omdat we zo de workflow gemakkelijk kunnen stoppen voor het geval het contact zich afmeldt van de mailinglijst.
Door dit workflow ID te specificeren voorkom je ook dat de workflow meerdere keren loopt, voor het geval iemand zich per ongeluk (of expres) meerdere keren op je mailinglijst inschrijft.
Als je geen workflow ID opgeeft, wordt er een willekeurige UUID aan toegekend, wat het erg moeilijk maakt de workflow te annuleren zonder dit willekeurige workflow ID in een andere database op te slaan.</p>
<h3 id="nieuwsbrief">De nieuwsbrief workflow</h3>
<p>We hebben gezien dat we een workflow kunnen uitvoeren op basis van een cron schema, maar de workflow doet nog niets.
Laten we daar verandering in brengen!
In de workflow moeten we 2 dingen doen:</p>
<ol>
<li>Haal de post op dat we onze abonnee willen sturen</li>
<li>Stuur de e-mail</li>
</ol>
<p>Deze workflow zou er ongeveer zo uit kunnen zien:</p>
<pre><code class="language-go">type Post struct {
    Title         string `json:"title"`
    Image         string `json:"image"`
    Description   string `json:"description"`
    URL           string `json:"url"`
    PostedDaysAgo int    `json:"posted_days_ago"`
}

w.RegisterActivityWithOptions(FetchLatestPost, activity.RegisterOptions{
    Naam: "post.fetch-latest",
})

w.RegistreerActiviteitMetOpties(SendPostmarkTemplate, activiteit.RegisterOpties{
    Naam: "email.send",
})

func EmailNewsletterWorkflow(ctx workflow.Context, config SubscribeRequest) error {

    // We willen beide activiteiten maximaal 10 keer opnieuw proberen.
    ctx = workflow.WithActivityOptions(ctx, workflow.ActivityOptions{
        TaskQueue:           Queue,
        StartToCloseTimeout: time.Minute,
        RetryPolicy: &amp;temporal.RetryPolicy{
            InitialInterval:    time.Second,
            BackoffCoefficient: 2.0,
            MaximumInterval:    time.Minute,
            MaximumAttempts:    10,
        },
    })

    var latestPost Post

    // Roep een API endpoint binnen een activiteit aan om de laatste post op te halen
    if err := workflow.
        ExecuteActivity(ctx, "post.fetch-latest").
        Get(ctx, &amp;latestPost); err != nil {
        return err
    }

    // We willen voorkomen dat we e-mails sturen als er de laatste 7 dagen geen nieuwe post was 
    if latestPost.PostedDaysAgo &gt; 7 {
        workflow.GetLogger(ctx).Info("latest post is posted more than 7 days ago, skipping...")
        return nil
    }

    if err := workflow.
        ExecuteActivity(ctx, "email.send", Config{
            TemplateAlias: "weekly-newsletter",
            Email:         config.Email,
            From:          "info@roelofjanelsinga.com",
            MessageStream: "newsletter",
            TemplateModel: map[string]interface{}{
                "title": latestPost.Title,
                "image": latestPost.Image,
                "description": latestPost.Description,
                "url": latestPost.URL,
            },
        }).
        Get(ctx, nil); err != nil {
        return err
    }

    return nil
}</code></pre>
<p>Deze workflow haalt de laatste post op en controleert of het in de afgelopen 7 dagen is geplaatst.
Als er in de afgelopen 7 dagen geen nieuwe post is geweest, is de workflow klaar en plant het een nieuwe workflow voor volgende week in.</p>
<p>Als er in de afgelopen 7 dagen een nieuwe post was, voert de workflow een activity uit die "email.send" heet, met de gegevens die de activity nodig heeft (Config).</p>
<p>Deze activity roept de Postmark API aan en stuurt het template met alias "weekly-newsletter" naar het contact dat we aan de workflow gegeven hebben.
In deze post hebben we deze e-mail hard gecodeerd als "hello@example.com".
De TemplateModel map in de configuratie zijn de variabelen die je in je Postmark template hebt gedefinieerd.
Je kunt ook kiezen om een struct te gebruiken in plaats van een map, maar ik hergebruik deze "email.send" activity voor elke workflow die emails verstuurt, dus dit maakt hem gemakkelijker te gebruiken voor mijn toepassing.</p>
<p>De activiteit voor het verzenden van e-mail is vrij eenvoudig en zet gewoon de Config om in een API oproep aan Postmark:</p>
<pre><code class="language-go">type PostmarkResponse struct {
    To          string
    SubmittedAt time.Time
    MessageID   string
    ErrorCode   int
    Message     string
}

type PostmarkFailure struct {
    ErrorCode int
    Message   string
}

func SendPostmarkTemplate(_ context.Context, config Config) (*PostmarkResponse, error) {

    client := sling.New().Base("https://api.postmarkapp.com")

    var success PostmarkResponse
    var failure PostmarkFailure

    _, err := client.
        Post("/email/withTemplate").
        Add("Accept", "application/json").
        Add("X-Postmark-Server-Token", "your-token-here").
        BodyJSON(Body{
            From:          config.From,
            To:            config.Email,
            TemplateID:    config.TemplateID,
            TemplateAlias: config.TemplateAlias,
            TemplateModel: config.TemplateModel,
            MessageStream: config.MessageStream,
        }).
        Receive(&amp;success, &amp;failure)

    if err != nil {
        return &amp;PostmarkResponse{
            ErrorCode: failure.ErrorCode,
            Message:   failure.Message,
        }, err
    }

    return &amp;success, nil
}</code></pre>
<p>We kunnen onze contacten nu abonneren op onze mailinglijst en hen wekelijks een e-mail sturen!
Helaas blijft niet elk contact voor onbepaalde tijd ingeschreven, dus moeten we afmeldingen afhandelen.
Laten we eens kijken hoe we dat kunnen doen!</p>
<h3 id="afmeldingen">Afmeldingen van de nieuwsbrief afhandelen</h3>
<p>&Atilde;&#137;&eacute;n van je contacten wil zich afmelden van je mailinglijst, dat is jammer!
Het is echter niet moeilijk om dit in onze applicatie te implementeren, want we hebben hier al aan gedacht toen we aan onze eerste workflow begonnen!</p>
<p>Herinner je je het workflow ID?
Die erg mooie en gemakkelijk te gebruiken workflow ID?
Dat zal dit uitschrijfproces veel...veel gemakkelijker maken!</p>
<p>Toen we de workflow voor dit contact uitvoerden, hebben we het workflow ID aangepast om het emailadres van het contact te bevatten: nieuwsbrief-hello@example.com.
Nu hebben we alleen nog maar hun email nodig om een contact uit te schrijven uit onze nieuwsbrief.</p>
<p>Omdat we een workflow met een cron schema gebruiken, kunnen we de workflow niet zomaar annuleren, want daardoor wordt een nieuwe workflow ingepland.
We willen dat de workflows niet meer gepland worden nadat het contact zich afmeldt, dus moeten we de workflow be&euml;indigen.</p>
<p>Zo ziet het er uit:</p>
<pre><code class="language-go">type UnsubscribeRequest struct {
    Email string `json:"email"`
}

func (s service) Unsubscribe(ctx context.Context, payload UnsubscribeRequest) error {
    err := s.client.TerminateWorkflow(ctx, fmt.Sprintf(WorkflowID, payload.Email), "", "afmelding")

    if err != nil {
        s.logger.Error("Error terminating workflow", err)
        return err
    }

    return nil
}</code></pre>
<p>De lege string die we aan de TerminateWorkflow methode doorgeven stelt het RunID voor.
Door dit RunID leeg te laten, neemt Temporal aan dat je de laatste run voor deze workflow wilt be&euml;indigen.</p>
<p>In de code zie je ook "afmelding" staan, dit is de reden van opzegging.
Het is een optioneel iets om toe te voegen, maar het is prettig als je in een team werkt en je afvraagt waarom je workflow wordt be&euml;indigd.</p>
<h2>Conclusie</h2>
<p>In deze post heb ik beschreven hoe ik mijn nieuwsbrieven van Mailchimp naar Postmark + Temporal heb gemigreerd.
Nu, met Postmark en Temporal, heb ik volledige controle over wie, hoe, en wat ik naar mijn mailinglijst stuur.
Het voordeel is dat ik nog steeds alle dingen kan doen die ik met Mailchimp kon, voor een fractie van de kosten.
Het nadeel van dit alles zelf bouwen is dat je technische expertise moet hebben en alle problemen die zich voordoen zelf moet oplossen.</p>
<p>Met die minpunten kan ik leven, want werken met zowel Postmark als Temporal is een genot!
Als iets onduidelijk is, heeft Temporal een geweldige gemeenschap om je te helpen.</p>
<p>Als je vragen hebt over dit proces, aarzel dan niet om contact op te nemen!</p></body></html>
]]></content>
                    <summary><![CDATA[Mailchimp is een geweldig SaaS platform om e-mails naar je abonnees te sturen, maar soms wil je meer controle over je e-mails hebben en niet 100+ per maand aan je e-mails uitgeven.]]></summary>
                    <media:content xmlns:media="http://search.yahoo.com/mrss/" url="https://aloia-systems.gumlet.io/images/articles/send-a-mail.jpg?s=5aab68d0e1db10fd0cf35ad45d4ce3dd" medium="image" type="image/jpeg" width="640" height="428" />
                  </entry>
<entry>
                    <title><![CDATA[Hoe je copywriting gebruikt om online te verkopen]]></title>
                    <link href="https://roelofjanelsinga.nl/articles/hoe-je-copywriting-gebruikt-om-online-te-verkopen/"/>
                    <id>https://roelofjanelsinga.nl/articles/hoe-je-copywriting-gebruikt-om-online-te-verkopen/</id>
                    <updated>2022-02-18T09:39:57+01:00</updated>
                    <published>2022-02-18T12:00:00+01:00</published>
                    <content type="html"><![CDATA[<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
<html><body><p><img src="https://aloia-systems.gumlet.io/images/articles/gold-pen-on-paper.jpg?w=640&amp;h=426&amp;s=7b165493775d44c47ff44bd1bfcad4e8" alt="Gouden pen op papier" loading="lazy" class="visibility-auto" title="Gouden pen op papier" srcset="https://aloia-systems.gumlet.io/images/articles/gold-pen-on-paper.jpg?w=320&amp;h=213&amp;mode=crop&amp;crop=smart&amp;s=f1f3be79c0acf174aedf0230d9054812 320w,https://aloia-systems.gumlet.io/images/articles/gold-pen-on-paper.jpg?w=480&amp;h=319&amp;mode=crop&amp;crop=smart&amp;s=aba9601d5650ea416514952473cda819 480w,https://aloia-systems.gumlet.io/images/articles/gold-pen-on-paper.jpg?w=640&amp;h=426&amp;mode=crop&amp;crop=smart&amp;s=84409c688950243dfd689d5cfd905fa7 640w" sizes="(max-width: 360px) 320px, max-width: 640px) 480px, 640px">
<span class="caption">Foto door <a href="https://unsplash.com/@artlasovsky">Art Lasovsky</a></span></p>
<h1>Hoe je copywriting gebruikt om online te verkopen</h1>
<p>Copywriting is een kunst EN een marketingstrategie, maar het wordt vaak over het hoofd gezien als een mogelijkheid om een verhaal, een product en een dienst te verkopen.
Copywriting is essentieel voor SEO en om uit te leggen wat het is dat je verkoopt en hoe het in de wereld past.
Dus hoe doe je dat effectief? Laten we daar eens achter komen!</p>
<p>In deze post leg ik 2 dingen uit: waarom copywriting essentieel is voor SEO, en hoe het je producten voor je kan verkopen.
Na het lezen van deze blog heb je duidelijke stappen die je kunt nemen om te beginnen met het schrijven van nieuwe teksten of het verbeteren van je huidige teksten.</p>
<p>Laten we beginnen met waarom copywriting essentieel is voor SEO en waarom je er niet te licht over moet denken.</p>
<h2>Copywriting is essentieel voor SEO</h2>
<p>Copywriting is essentieel voor SEO, want het maakt je website doorzoekbaar en helpt duidelijk te maken waarom je product of dienst nodig is.
Zonder ondersteunende teksten laat je je potenti&euml;le klanten achter met meer vragen dan antwoorden.
Waarom zouden je potenti&euml;le klanten betalen voor wat je verkoopt als ze niet begrijpen wat het is dat je verkoopt?
Goede copywriting legt uit wat het is dat je doet, wat je een boost in Google geeft voor de relevante zoektermen.
Je wilt gevonden worden op zoektermen die relevant zijn voor je bedrijf, anders trek je niet de bezoekers aan die klanten worden.</p>
<h3>Context is de belangrijk</h3>
<p>Zoekmachines zijn tegenwoordig heel slim in het vergaren van context voor je website, door uit te zoeken hoe die in het internet past.
Als je copywriting helpt om je producten en diensten uit te leggen, door context te geven aan je bedrijf, help je de zoekmachines om je te begrijpen.
Dit geeft je de gelegenheid om de zoekmachines te be&iuml;nvloeden door je eigen context te geven van wie je bent.
Maar wat betekent dit?
Laten we dat uitzoeken in het volgende deel over hoe je copywriting kunt gebruiken om je product of dienst ook echt te verkopen.</p>
<h2>Hoe je copywriting gebruikt om te verkopen</h2>
<p><img src="https://aloia-systems.gumlet.io/images/articles/shaking-hands.jpg?w=640&amp;h=426&amp;s=11a21ebd559f8823b4cc66acb0566657" alt="Handen schudden" loading="lazy" class="visibility-auto" title="Handen schudden" srcset="https://aloia-systems.gumlet.io/images/articles/shaking-hands.jpg?w=320&amp;h=213&amp;mode=crop&amp;crop=smart&amp;s=1e91d79e5095c66b75f7b916bbf8d832 320w,https://aloia-systems.gumlet.io/images/articles/shaking-hands.jpg?w=480&amp;h=319&amp;mode=crop&amp;crop=smart&amp;s=8d2091ab1a2364a51455795cf7aa09ac 480w,https://aloia-systems.gumlet.io/images/articles/shaking-hands.jpg?w=640&amp;h=426&amp;mode=crop&amp;crop=smart&amp;s=0c9af6718a2dda9bf513b396dbf9b11a 640w" sizes="(max-width: 360px) 320px, max-width: 640px) 480px, 640px">
<span class="caption">Foto door <a href="https://unsplash.com/@cytonn_photography">Cytonn Photography</a></span>.</p>
<p>In het vorige gedeelte hebben we gezien dat copywriting essentieel is voor SEO.
Maar nu vraag je je misschien af: hoe schrijf je teksten die verkopen?
Het belangrijkste is dat je glashelder bent en alle nuance, regionaal jargon en algemene vaagheid uit je tekst verwijdert.</p>
<h3>Wees glashelder</h3>
<p>Je kunt je SEO en sales verbeteren als je met je copywriting glashelder bent over wat het is dat je doet.
Er is geen plaats voor nuances en vage teksten in SEO: Wees glashelder over wat je doet of verkoopt.
Voorbeeld: "We laten je auto weer glimmen" wordt "We maken je auto schoon voor 5 euro".
Dit stelt de verwachtingen vooraf en is ook een SEO-vriendelijke titel.</p>
<h3>Vertel een verhaal</h3>
<p>Glasheldere teksten gebruiken is de eerste stap, maar het verkoopt niets als je geen verhaal vertelt.
Een verhaal vertellen met je glasheldere teksten lijkt op het eerste gezicht misschien tijdverspilling, maar het is het ontbrekende ingredi&euml;nt dat je product of dienst zal verkopen.
Storytelling neemt je potenti&euml;le klant mee op een reis langs 4 stappen:</p>
<ol>
<li>Ontdekking: Wat verkoop je? </li>
<li>Probleem: Wat houdt me tegen om grootsheid te bereiken? </li>
<li>Waardevoorstel: Waarom heb ik nodig wat jij verkoopt? </li>
<li>Acquisitie: Hoe kan ik aan je product of dienst komen?</li>
</ol>
<p>Als je stap 1 tot en met 4 overslaat, voelt het aan als een koud telefoontje: "H&eacute; we hebben product X, koop het nu voor 99 euro".
Je zult hoogstwaarschijnlijk zeggen: "Nee dank je, ik ben niet ge&iuml;nteresseerd".
Zelfs als product X al je problemen had kunnen oplossen, dan nog heeft de verkoper je nooit precies verteld welke problemen het oplost en waarom het goed bij je situatie past.
Er is geen relatie tussen de verkoper en de koper.
De verkoper kent de situatie van de koper niet en gokt erop dat je het zult willen hebben.
De koper vertrouwt de aanbeveling van de verkoper niet, want deze hele situatie is gebaseerd op een grote gok.</p>
<p>Een website is eenrichtingsverkeer: De koper heeft interactie met je website, maar jij kunt (meestal) niet direct met de koper communiceren.
Dit lijkt een beetje op het koude telefoontje van hierboven, maar je kunt copywriting gebruiken om vertrouwen te scheppen tussen jou en je potenti&euml;le klant bij deze eenrichtingsinteractie.
Hoe bouw je vertrouwen op in een eenrichtingsrelatie?
Laten we het uitzoeken!</p>
<h3>Bouw vertrouwen op met je potenti&euml;le klant</h3>
<p>In een eenrichtingsrelatie met je klant op je website, kun je nog steeds vertrouwen opbouwen tussen jou en je bezoekers.
Je zult al je kaarten op tafel moeten leggen door in je copywriting al deze vragen te beantwoorden:</p>
<ol>
<li>Voor wie is je product of dienst bestemd? </li>
<li>Met welke precieze problemen hebben je potenti&euml;le klanten te maken? </li>
<li>Wat verkoop je? </li>
<li>Hoe lost je product of dienst deze precieze problemen op? </li>
<li>Hoeveel zal het kosten? </li>
<li>Hoe kunnen je potenti&euml;le klanten je product kopen of een afspraak maken?</li>
</ol>
<p>Een goede vuistregel voor het beantwoorden van deze vragen is deze: Hoe specifieker hoe beter.
De volgorde van de vragen is opzettelijk: Je wilt dat de potenti&euml;le klanten zich gezien voelen voor je hen vraagt bij je te kopen.
Maar onthoud: je MOET ze te vragen om bij je te kopen!
Je moet ze de optie geven om te kopen of je aanbod af te wijzen.</p>
<h2>Conclusie</h2>
<p>In deze post hebben we gezien waarom copywriting essentieel is voor SEO en het verkopen van je product of dienst.
Copywriting helpt je je product te verkopen als het glashelder is, een verhaal vertelt, en vertrouwen wekt bij je potenti&euml;le klanten.
Ik heb geschetst hoe je je copywriting kunt verbeteren door je specifieke vragen te geven die je zult moeten beantwoorden in jouw teksten.
Goede copywriting kan je website omzetten van ploeteren tot je omzet brengen, maar je moet er wel prioriteit aan geven.</p></body></html>
]]></content>
                    <summary><![CDATA[Copywriting is een kunst en een marketingstrategie, maar het wordt vaak over het hoofd gezien als een mogelijkheid om een verhaal, een product of een dienst te verkopen. Copywriting is essentieel voor SEO en om context te geven aan wat je verkoopt. Dus hoe doe je dat effectief? Laten we daar achter komen!]]></summary>
                    <media:content xmlns:media="http://search.yahoo.com/mrss/" url="https://aloia-systems.gumlet.io/images/articles/gold-pen-on-paper.jpg?s=af66cb6bc515775b3e2cc027920fb567" medium="image" type="image/jpeg" width="640" height="428" />
                  </entry>
<entry>
                    <title><![CDATA[Speel het lange SEO spel]]></title>
                    <link href="https://roelofjanelsinga.nl/articles/speel-het-lange-seo-spel/"/>
                    <id>https://roelofjanelsinga.nl/articles/speel-het-lange-seo-spel/</id>
                    <updated>2022-01-02T15:08:45+01:00</updated>
                    <published>2021-12-31T12:00:00+01:00</published>
                    <content type="html"><![CDATA[<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
<html><body><p><img src="https://aloia-systems.gumlet.io/images/articles/audience-on-whiteboard.jpg?w=640&amp;h=426&amp;s=4bc7cf6cc1ad7cd8856572635c80e247" alt="Publiek op whiteboard" loading="lazy" class="visibility-auto" title="Publiek op whiteboard" srcset="https://aloia-systems.gumlet.io/images/articles/audience-on-whiteboard.jpg?w=320&amp;h=213&amp;mode=crop&amp;crop=smart&amp;s=0edb1f2643b3eef58908f863a5c2b2cb 320w,https://aloia-systems.gumlet.io/images/articles/audience-on-whiteboard.jpg?w=480&amp;h=319&amp;mode=crop&amp;crop=smart&amp;s=51c8e39105d280bced77c2231fa8267b 480w,https://aloia-systems.gumlet.io/images/articles/audience-on-whiteboard.jpg?w=640&amp;h=426&amp;mode=crop&amp;crop=smart&amp;s=ec4c48fc12600d7494ae838e57cfeeec 640w" sizes="(max-width: 360px) 320px, max-width: 640px) 480px, 640px">
<span class="caption">Foto door <a href="https://unsplash.com/@storyfuel">Melanie Deziel</a> op Unsplash</span>.</p>
<h1>Speel het lange SEO spel</h1>
<p>Als je het gevoel hebt dat je bedrijf of website niet het zoekverkeer krijgt dat je denkt dat het verdient, dan ben je niet de enige.
Veel bedrijfseigenaren hebben dit gevoel en huren SEO specialisten in om hen te helpen hun doelen te bereiken.</p>
<p>Maar zelfs met de grootste SEO specialist is het nog steeds een goed idee om te begrijpen hoe SEO werkt en waarom wat je wilt misschien niet het beste is voor je bedrijf.
Laten we de voordelen onderzoeken van het spelen van het lange SEO spel en waarom het een veel effectievere marketing strategie voor je bedrijf kan zijn.</p>
<p>Laten we de SEO hacks overslaan, want die zijn vaak erg duur en komen jou of je bedrijf op de lange termijn niet ten goede.
Speel het lange spel!</p>
<h2>Wat is het lange SEO spel?</h2>
<p>Het lange SEO spel is eenvoudig: Je investeert veel (tijd, moeite, en kapitaal) om je website zo nuttig mogelijk te maken.
In de praktijk betekent dit dat je 3 dingen goed moet doen:</p>
<ul>
<li>Leg in heel gewone, niet-jargon-achtige woorden precies uit wat het is dat je doet</li>
<li>Laat je expertise voortdurend aan de wereld zien door behulpzaam te zijn voor je doelgroep</li>
<li>Heb een technisch uitstekende website</li>
</ul>
<p>Deze SEO strategie zal niet gebouwd zijn op snelle SEO overwinningen, maar zal je naarmate de tijd verstrijkt exponentieel groeiend verkeer schenken.
Ik weet hoe vaag en frustrerend dit klinkt, er is gewoon geen specifieke tijdlijn voor deze strategie.
Er is geen tijdlijn, want Google &amp; vrienden veranderen hun algoritmes dagelijks, waardoor je eerder voordeel kunt hebben of langer zult moeten wachten.</p>
<p>Deze SEO strategie is een beetje als investeren in de aandelenmarkt: Je kijkt naar het langetermijnplaatje.
Google kan je van dag tot dag belonen of straffen, maar als je deze strategie volhoudt zul je er op lange termijn enorm veel profijt van hebben.</p>
<p>Genoeg begrippen, laten we de 3 dingen uitlichten die je goed moet doen om het lange SEO spel te spelen.</p>
<h2>Leg precies uit wat het is dat je doet</h2>
<p>Hoe zullen mensen je bedrijf of dienst vinden als je je doelgroep nooit expliciet vertelt wat je doet?
Het harde antwoord is: ze zullen je niet vinden.</p>
<p>Bijvoorbeeld, als je bedrijf auto's schoonmaakt en alles wat je website zegt is "We laten je auto er weer als nieuw uitzien", zullen mensen je bedrijf niet vinden.
Je doelgroep zal zoeken op termen als "wasstraat bij mij in de buurt" of "auto snel schoonmaken".
Een betere titel/kop zou zijn: We maken je auto schoon om het in 15 minuten te laten glimmen.
Wees glashelder over wat het is dat je doet en gebruik gewone woorden.</p>
<p>Je website verkoopt je producten en/of diensten, dus moet je heel duidelijk maken wat het is dat je verkoopt.
Je kunt alle pakkende woorden gebruiken die je wilt om je producten of diensten te omschrijven, maar dat zijn niet de woorden waar je doelgroep naar zal zoeken.
Denk zoals je doelgroep en gebruik woorden die zij zouden gebruiken.</p>
<h3>Test jezelf</h3>
<p>Als je de eenvoudige vraag "Hoe help ik mijn klant?" niet kunt beantwoorden, ben je nog niet klaar om je SEO te optimaliseren.
Als je niet weet hoe je je klant helpt, hoe zullen zij dat dan weten?</p>
<p>Voor je verder gaat met de volgende stap in het lange SEO spel, moet je een heel duidelijk antwoord op deze vraag hebben.
Je antwoord mag alleen gewone woorden bevatten en mag maximaal 2 zinnen lang zijn.</p>
<p>Een goede manier om je zinnen te testen is om iemand die 2 zinnen te vertellen en hen dan te vragen wat je doet.
Als ze je kunnen uitleggen wat je doet, ben je klaar om verder te gaan.</p>
<h2>Laat consequent je deskundigheid zien door behulpzaam te zijn</h2>
<p>Weet je wat Google graag doet?
Google helpt mensen graag door vragen te beantwoorden en ze naar bronnen te brengen die helpen om die vragen te beantwoorden.
Idealiter wil Google deze vragen zo effici&euml;nt mogelijk beantwoorden.</p>
<h3>Hoe Google nuttige pagina's vindt</h3>
<p>Google &amp; Friends zien graag gebruikersstromen waarin de gebruiker van een vaag idee naar een hele specifieke vraag gaat.
Als iemand deze reis doormaakt, leert hij of zij onderweg iets nieuws om hen te helpen betere vragen te stellen.
Hoe specifieker de vraag, hoe beter je kunt helpen.</p>
<p>Dit is wat Google graag ziet:</p>
<p><img src="https://aloia-systems.gumlet.io/images/articles/desired-search-behavior.jpg?w=640&amp;h=426&amp;s=4659b3350702bb1ce74ce5d567454de7" alt="Gewenst zoekgedrag op Google" loading="lazy" class="visibility-auto" title="Gewenst zoekgedrag op Google" srcset="https://aloia-systems.gumlet.io/images/articles/desired-search-behavior.jpg?w=320&amp;h=213&amp;mode=crop&amp;crop=smart&amp;s=7a6f03333057bf61488c7a4d56536db8 320w,https://aloia-systems.gumlet.io/images/articles/desired-search-behavior.jpg?w=480&amp;h=319&amp;mode=crop&amp;crop=smart&amp;s=aef6f950ce78bc5098d93e9f77372e53 480w,https://aloia-systems.gumlet.io/images/articles/desired-search-behavior.jpg?w=640&amp;h=426&amp;mode=crop&amp;crop=smart&amp;s=7491b830fe0dc997eadc58880ca686b3 640w" sizes="(max-width: 360px) 320px, max-width: 640px) 480px, 640px"></p>
<ol>
<li>Bezoeker stelt een vraag </li>
<li>Bezoeker bezoekt je website en leest wat je te vertellen hebt </li>
<li>Bezoeker keert terug naar Google </li>
<li>Bezoeker stelt een andere, meer specifieke, vraag</li>
</ol>
<p>Deze stroom van acties betekent dat je website de bezoeker iets geleerd heeft en hem geholpen heeft beter te begrijpen wat hij werkelijk nodig heeft.
Google markeert deze pagina nu als nuttig voor de volgende persoon die langskomt.</p>
<h3>Hoe Google slechte inhoud vindt</h3>
<p>Maar Google weet het ook als je niet succesvol bent in het beantwoorden van de vraag van deze bezoeker.
Als je er niet in geslaagd bent je bezoeker behulpzaam te zijn, zullen ze proberen op een andere website meer te weten te komen.</p>
<p>Zo ziet een niet-succesvolle stroom eruit:</p>
<p><img src="https://aloia-systems.gumlet.io/images/articles/how-google-finds-bad-content.jpg?w=640&amp;h=426&amp;s=42730b2eaa52cfd08f8cc36c673251df" alt="Hoe Google slechte inhoud vindt" loading="lazy" class="visibility-auto" title="Hoe Google slechte inhoud vindt" srcset="https://aloia-systems.gumlet.io/images/articles/how-google-finds-bad-content.jpg?w=320&amp;h=213&amp;mode=crop&amp;crop=smart&amp;s=3192d6cb6157ef50ab6b2f33569720d9 320w,https://aloia-systems.gumlet.io/images/articles/how-google-finds-bad-content.jpg?w=480&amp;h=319&amp;mode=crop&amp;crop=smart&amp;s=f7e3c172f8366215c7f113788d50464b 480w,https://aloia-systems.gumlet.io/images/articles/how-google-finds-bad-content.jpg?w=640&amp;h=426&amp;mode=crop&amp;crop=smart&amp;s=9fe506a431087d399ad50f44b9c3d2ff 640w" sizes="(max-width: 360px) 320px, max-width: 640px) 480px, 640px"></p>
<ol>
<li>Bezoeker stelt een vraag</li>
<li>Bezoeker bezoekt je website en leest wat je te vertellen hebt</li>
<li>Bezoeker keert terug naar Google</li>
<li>Bezoeker klikt op een andere link met dezelfde zoektermen</li>
</ol>
<p>Blijkbaar vond de bezoeker op je website niet wat hij of zij zocht en probeert het opnieuw bij een andere website.
Google weet nu dat de pagina niet nuttig was voor deze zoekterm en zal het de volgende keer dat iemand op die term zoekt minder prioriteit geven.</p>
<h3>De positieve of negatieve terugkoppelingslus</h3>
<p>Nu we weten hoe Google goede en slechte inhoud vindt en hoe het deze pagina's rangschikt, begin je een terugkoppelingslus te zien.
Als je succesvol bent in het helpen van je bezoekers en Google ziet dat je waarde toevoegt aan hun zoekervaring, dan belonen ze je.</p>
<p>Als je consequent hun algoritme helpt door vragen te beantwoorden, kom je in een positieve feedback kringloop.
Deze positieve terugkoppelingslus ziet er als volgt uit:</p>
<p><img src="https://aloia-systems.gumlet.io/images/articles/positive-feedback-loop-SEO.jpg?w=640&amp;h=426&amp;s=3a860e14df5a7492651fa09d9c067f6b" alt="Positieve feedback-lus voor SEO" loading="lazy" class="visibility-auto" title="Positieve feedback-lus voor SEO" srcset="https://aloia-systems.gumlet.io/images/articles/positive-feedback-loop-SEO.jpg?w=320&amp;h=213&amp;mode=crop&amp;crop=smart&amp;s=63e0d2728d761e19d5759cf03b2fb260 320w,https://aloia-systems.gumlet.io/images/articles/positive-feedback-loop-SEO.jpg?w=480&amp;h=319&amp;mode=crop&amp;crop=smart&amp;s=268d210d99d29d51fdd39ed597b803c8 480w,https://aloia-systems.gumlet.io/images/articles/positive-feedback-loop-SEO.jpg?w=640&amp;h=426&amp;mode=crop&amp;crop=smart&amp;s=137a8ccc76f71d6132cef34336f0f426 640w" sizes="(max-width: 360px) 320px, max-width: 640px) 480px, 640px"></p>
<ol>
<li>Google ziet dat je behulpzaam voor hen bent</li>
<li>Google rangschikt je webpagina hoger in hun resultaten</li>
<li>Je nieuwe inhoud zal sneller opgepikt worden, omdat je de vorige keer behulpzaam was</li>
<li>Je krijgt meer verkeer op bestaande EN nieuwe inhoud</li>
</ol>
<p>Je wilt dat je website in deze positieve feedback loop komt, want het is bijna passieve marketing.
Als de inhoud er eenmaal is, hoef je er niet al te veel meer naar om te kijken.
Je zult het moeten bijwerken als het verouderd raakt, anders begint deze feedback loop tegen je te werken.
Als je inhoud verouderd is, ben je niet meer nuttig en verlies je langzaam het verkeer waar je zo hard voor gewerkt hebt.</p>
<p>Je komt in een negatieve terugkoppelingslus terecht.
Dit is hoe een negatieve terugkoppelingslus eruit ziet:</p>
<p><img src="https://aloia-systems.gumlet.io/images/articles/negative-feedback-loop-SEO.jpg?w=640&amp;h=426&amp;s=e0135fa05d7067815c04221d1e15a617" alt="Negatieve feedback-lus voor SEO" loading="lazy" class="visibility-auto" title="Negatieve feedback-lus voor SEO" srcset="https://aloia-systems.gumlet.io/images/articles/negative-feedback-loop-SEO.jpg?w=320&amp;h=213&amp;mode=crop&amp;crop=smart&amp;s=c0a8067d9bd9d9739336d815277fbcae 320w,https://aloia-systems.gumlet.io/images/articles/negative-feedback-loop-SEO.jpg?w=480&amp;h=319&amp;mode=crop&amp;crop=smart&amp;s=d188a58fbb818525ee88e7f79ba97ef3 480w,https://aloia-systems.gumlet.io/images/articles/negative-feedback-loop-SEO.jpg?w=640&amp;h=426&amp;mode=crop&amp;crop=smart&amp;s=349ec6c0e34b3fbe7cb835c8e481dde6 640w" sizes="(max-width: 360px) 320px, max-width: 640px) 480px, 640px"></p>
<p>Deze negatieve feedback lussen zijn het beste argument dat je geen SEO hacks moet gebruiken om je pagina's te helpen ranken.
Algoritmen veranderen, maar goede en nuttige inhoud presteert goed en overleeft gemakkelijker algoritmeveranderingen.</p>
<h2>Heb een technisch uitstekende website</h2>
<p>Iedereen weet dat Google houdt van snelle websites met een goede gebruikerservaring (UX).
Daarom steken bedrijfseigenaren vaak de meeste moeite in dit deel van SEO.
Je kunt de snelste website ter wereld hebben, maar als je geen waarde toevoegt aan de zoekervaring van je bezoekers, zul je niet zo snel groeien als je zou kunnen.
Google zal geen goede reden hebben om je pagina's te rangschikken, dus je doelgroep zal je nog steeds niet vinden.</p>
<p>Trage websites zijn niet geweldig voor de zoekresultaten, maar het is niet de enige factor die meespeelt bij goede SEO.
Dat gezegd hebbende, moet je nog steeds alles doen wat je kunt om een stevige basis te krijgen, een snelle website.
Een snelle website is altijd mooi, maar dat alleen zal je producten of diensten niet verkopen.</p>
<p>Als je de snelle website hebt, kun je je concentreren op de dingen die je producten of diensten werkelijk zullen verkopen: kristalheldere woorden en het tonen van je deskundigheid.
Deze 2 onderdelen helpen mensen je te vinden en helpen hen ervan te overtuigen dat je de beste bent in wat je doet en dat ze je absoluut moeten aannemen.</p>
<h2>Hulp nodig om het lange SEO spel te spelen?</h2>
<p>Wil je je eigen SEO vriendelijke website bouwen om je bedrijf te laten groeien en de resultaten te krijgen die je wilt?
Dat is fantastisch, je zult niet teleurgesteld zijn!</p>
<p>Als je niet zeker weet waar je moet beginnen of gewoon iemand wilt die je helpt je zakelijke doelen te bereiken, dan ben ik in te huren!
Je krijgt de tijd om je te concentreren op wat je het beste kunt: je bedrijf draaien en je richten op de verkoop.
Ik help je de positieve feedback loop die ik in dit artikel heb beschreven in te voeren en je website naar een hoger niveau te tillen.</p></body></html>
]]></content>
                    <summary><![CDATA[Snelle SEO hacks zijn erg populair, maar komen jou of je bedrijf op lange termijn niet ten goede. SEO hacks zijn duur en worden vaak door Google bestraft. Geweldige SEO komt van behulpzaam zijn en glashelder zijn in je berichtgeving. Speel het lange SEO spel!]]></summary>
                    <media:content xmlns:media="http://search.yahoo.com/mrss/" url="https://aloia-systems.gumlet.io/images/articles/audience-on-whiteboard.jpg?s=a6151addcd7f225d197037ad0bb3b22c" medium="image" type="image/jpeg" width="640" height="428" />
                  </entry>

</feed>