<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Thibault Milan</title>
    <description>The latest articles on DEV Community by Thibault Milan (@clawfire).</description>
    <link>https://dev.to/clawfire</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F33972%2Fde3790d9-8519-452a-ba05-702e81bfe02d.jpg</url>
      <title>DEV Community: Thibault Milan</title>
      <link>https://dev.to/clawfire</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/clawfire"/>
    <language>en</language>
    <item>
      <title>Shipping Fast(er): How I Used Claude Code to Release Chrome Webhook Extension 2.0</title>
      <dc:creator>Thibault Milan</dc:creator>
      <pubDate>Sun, 29 Jun 2025 07:56:04 +0000</pubDate>
      <link>https://dev.to/clawfire/shipping-faster-how-i-used-claude-code-to-release-chrome-webhook-extension-20-3fcc</link>
      <guid>https://dev.to/clawfire/shipping-faster-how-i-used-claude-code-to-release-chrome-webhook-extension-20-3fcc</guid>
      <description>&lt;h2&gt;
  
  
  A Tale of Side Projects and Speed
&lt;/h2&gt;

&lt;p&gt;There’s a unique satisfaction in shipping something you built for yourself. That feeling gets even better when you manage to revive a side project after a long pause—and ship not just a fix, but a full version bump.&lt;/p&gt;

&lt;p&gt;This post is about &lt;a href="https://github.com/clawfire/chrome-webhook-extension" rel="noopener noreferrer"&gt;Chrome Webhook Extension&lt;/a&gt;, a small tool I first wrote to make it easier to send browser data to a webhook (like a Discord channel, a Notion automation, or anything you can connect). It sat untouched for a while—until I decided to pick it up again with the help of Claude Code, an AI-powered coding agent. The result? A productive two-day burst that gave life to version 1.2 and then, less than 24 hours later, version 2.0.&lt;/p&gt;

&lt;p&gt;Here’s what changed, and how AI helped me build faster.&lt;/p&gt;

&lt;h2&gt;
  
  
  What’s New in v2.0
&lt;/h2&gt;

&lt;p&gt;If you were using the extension before, you might not notice radical UI changes—but under the hood, v2.0 introduces a more robust foundation and thoughtful improvements to workflows. Here’s a quick breakdown:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Webhook test mode&lt;/strong&gt;: You can now test your webhook without sending real data. Super handy for debugging.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Improved error handling&lt;/strong&gt;: Webhook requests now catch and display error messages more transparently.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cleaner UI alignment&lt;/strong&gt;: Better alignment and spacing across popup views.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Code refactoring&lt;/strong&gt;: The codebase is cleaner and easier to maintain, especially around popup logic and validation.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Safer UX&lt;/strong&gt;: Edge cases are now handled more gracefully when URLs or payloads are missing.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can find the full release notes for &lt;a href="https://github.com/clawfire/chrome-webhook-extension/releases/tag/v2.0.0" rel="noopener noreferrer"&gt;v2.0 here&lt;/a&gt;, and &lt;a href="https://github.com/clawfire/chrome-webhook-extension/releases/tag/v1.2" rel="noopener noreferrer"&gt;v1.2 here&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Working With Claude Code: The Real Productivity Boost
&lt;/h2&gt;

&lt;p&gt;Both the 1.2 and 2.0 versions were built using &lt;strong&gt;Claude Code&lt;/strong&gt;, a development assistant built on top of Anthropic’s Claude 3.5 family. I primarily used &lt;strong&gt;Claude 3.5 Haiku&lt;/strong&gt;, with some calls handled by &lt;strong&gt;Sonnet&lt;/strong&gt; and &lt;strong&gt;Opus&lt;/strong&gt;, depending on the complexity of the task. But most of the time, I didn’t have to choose—Claude Code’s agent handled that.&lt;/p&gt;

&lt;p&gt;Here’s a fun stat:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;v1.2&lt;/strong&gt; took me &lt;strong&gt;1h15&lt;/strong&gt; to build — and cost me &lt;strong&gt;\$3.02&lt;/strong&gt; of tokens&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;v2.0&lt;/strong&gt; took me &lt;strong&gt;1h40&lt;/strong&gt; — and cost me &lt;strong&gt;\$4.63&lt;/strong&gt; of tokens&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That’s under 3 hours total for two solid updates to a production-ready extension, at a price point that’s cheaper than a decent lunch. What’s more interesting is &lt;em&gt;how much&lt;/em&gt; Claude Code actually handled:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Debugging issues I had previously written (but not committed yet)&lt;/li&gt;
&lt;li&gt;Suggesting clearer code structures overall&lt;/li&gt;
&lt;li&gt;Reworking event listener placement and associated logic&lt;/li&gt;
&lt;li&gt;Managing edge use cases and improving input sanitisation&lt;/li&gt;
&lt;li&gt;Handling a complete UX refactoring, moving from basic to polished while keeping PureCSS&lt;/li&gt;
&lt;li&gt;Helping draft the release notes and Chrome Web Store description&lt;/li&gt;
&lt;li&gt;Writing the GitHub logic to treat issues as a lightweight support ticketing system&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In short: it felt like having a reliable mid-level dev on my team—one that needed some oversight, but consistently offered solid structure, relevant suggestions, and kept things moving forward. Definitely not junior-level like what IDE autocomplete or tools like Lovable tend to provide.&lt;/p&gt;

&lt;h2&gt;
  
  
  Making Side Projects Realistic Again
&lt;/h2&gt;

&lt;p&gt;Before this update, this extension had been sitting mostly untouched. Like many devs, I have a backlog of ideas or half-finished tools that I &lt;em&gt;want&lt;/em&gt; to complete but can’t justify sinking hours into after work. But pairing with Claude Code made the time investment feel much more feasible:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The feedback loop is &lt;em&gt;fast&lt;/em&gt;. Ask, try, tweak, ship.&lt;/li&gt;
&lt;li&gt;It doesn't get stuck or tired—or need you to write full spec docs.&lt;/li&gt;
&lt;li&gt;It helps re-enter old codebases by explaining and cleaning up context.&lt;/li&gt;
&lt;li&gt;It can even execute bash instructions, with per-command approval or predefined permission scopes. I let it handle &lt;code&gt;git commit&lt;/code&gt;, &lt;code&gt;push&lt;/code&gt;, and &lt;code&gt;pull&lt;/code&gt;, but kept &lt;code&gt;tag&lt;/code&gt; and &lt;code&gt;rebase&lt;/code&gt; under manual control.&lt;/li&gt;
&lt;li&gt;This means it doesn’t just write code—it can ship the whole cycle if you let it.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;What would have taken a full weekend of grumbling and Googling ended up being an evening project with real output.&lt;/p&gt;

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

&lt;p&gt;I’m planning a few more internal improvements, and maybe support for templating common payloads. But what really excites me is diving deeper into what Claude Code can do. I haven’t even tried connecting it to tools via the MCP protocol yet—imagine it working on my database, managing Netlify functions, or integrating directly with other cloud-native services.&lt;/p&gt;

&lt;p&gt;There’s a lot more I want to explore, and I’ll definitely share if it turns into something interesting.&lt;/p&gt;

&lt;p&gt;If you try it and have feedback, &lt;a href="https://github.com/clawfire/chrome-webhook-extension/issues" rel="noopener noreferrer"&gt;open an issue&lt;/a&gt; or ping me.&lt;/p&gt;

&lt;h2&gt;
  
  
  Final Thoughts
&lt;/h2&gt;

&lt;p&gt;If you’re juggling a busy schedule and a drawer full of side projects, consider giving Claude Code or a similar AI dev tool a try. It won’t &lt;em&gt;replace&lt;/em&gt; your judgement, but it will absolutely make it easier to get over the hump and just ship.&lt;/p&gt;

&lt;p&gt;🔗 &lt;a href="https://chromewebstore.google.com/detail/webhook-manager/bgmeeebkokmefcfafnhfjgbemifefbno" rel="noopener noreferrer"&gt;Chrome Webhook Extension on Chrome Web Store&lt;/a&gt;&lt;br&gt;
🔗 &lt;a href="https://github.com/clawfire/chrome-webhook-extension" rel="noopener noreferrer"&gt;Chrome Webhook Extension on GitHub&lt;/a&gt;&lt;br&gt;
📦 &lt;a href="https://github.com/clawfire/chrome-webhook-extension/releases/tag/v2.0.0" rel="noopener noreferrer"&gt;Download v2.0&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Automate Netlify Rebuilds Using GitHub Actions</title>
      <dc:creator>Thibault Milan</dc:creator>
      <pubDate>Sun, 22 Jun 2025 14:21:00 +0000</pubDate>
      <link>https://dev.to/clawfire/automate-netlify-rebuilds-using-github-actions-2b4a</link>
      <guid>https://dev.to/clawfire/automate-netlify-rebuilds-using-github-actions-2b4a</guid>
      <description>&lt;p&gt;Static site generators like Jekyll or Eleventy support scheduling content via the &lt;code&gt;date:&lt;/code&gt; field in the YAML frontmatter. But these future-dated posts won’t appear on your site unless it’s rebuilt — and Netlify only rebuilds when a new commit is pushed.&lt;/p&gt;

&lt;p&gt;This can be a problem when you're scheduling posts for the future: unless something triggers a new build on the right day, those posts won't go live.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why an automated (but smart) rebuild?
&lt;/h2&gt;

&lt;p&gt;Rebuilding the site every day is one option, but that can quickly consume your &lt;strong&gt;300 monthly build minutes&lt;/strong&gt; on Netlify's free tier. If a rebuild takes ~4 minutes, a daily schedule eats up 40% of your budget.&lt;/p&gt;

&lt;p&gt;The smarter approach? &lt;strong&gt;Only rebuild when a post is actually due.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  🧠 The smarter strategy: conditional scheduling
&lt;/h2&gt;

&lt;p&gt;Here’s how the workflow works:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;On each commit that modifies a Markdown file, GitHub Actions checks if a future &lt;code&gt;date:&lt;/code&gt; is present in the file (even if it's in full ISO 8601 format).&lt;/li&gt;
&lt;li&gt;If it finds one, the next scheduled date is extracted and saved into a &lt;code&gt;next-build.txt&lt;/code&gt; file.&lt;/li&gt;
&lt;li&gt;Instead of committing this file (which would trigger a Netlify rebuild), it’s stored as a &lt;strong&gt;GitHub artifact&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;A lightweight scheduled workflow runs daily, downloads the artifact, and checks whether today matches the date.&lt;/li&gt;
&lt;li&gt;If it matches, it triggers a Netlify build via webhook.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  🔧 Netlify: Setup a build webhook
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Go to your Netlify site dashboard.&lt;/li&gt;
&lt;li&gt;Navigate to &lt;strong&gt;Site settings &amp;gt; Build &amp;amp; deploy &amp;gt; Build hooks&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Click &lt;strong&gt;Add build hook&lt;/strong&gt;, give it a name (e.g. “Scheduled rebuild”), and choose your deploy branch (e.g. &lt;code&gt;main&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;Copy the webhook URL and save it as a GitHub secret named &lt;code&gt;NETLIFY_BUILD_HOOK&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  Workflow 1: Detect future dates (on push)
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Prepare next Netlify build date&lt;/span&gt;

&lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;push&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;paths&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;_posts/**.md"&lt;/span&gt;

&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;extract-next-build-date&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;
    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/checkout@v4&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Extract future post date&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
          &lt;span class="s"&gt;TODAY=$(date '+%Y-%m-%d')&lt;/span&gt;
          &lt;span class="s"&gt;FUTURE_DATES=()&lt;/span&gt;
          &lt;span class="s"&gt;for FILE in $(git diff --name-only HEAD^ HEAD | grep '\.md$'); do&lt;/span&gt;
            &lt;span class="s"&gt;[ -f "$FILE" ] || continue&lt;/span&gt;
            &lt;span class="s"&gt;POST_DATE=$(grep '^date:' "$FILE" | head -n1 | sed -E 's/date: *"?([0-9]{4}-[0-9]{2}-[0-9]{2}).*/\1/')&lt;/span&gt;
            &lt;span class="s"&gt;if [[ "$POST_DATE" &amp;gt; "$TODAY" ]]; then&lt;/span&gt;
              &lt;span class="s"&gt;FUTURE_DATES+=("$POST_DATE")&lt;/span&gt;
            &lt;span class="s"&gt;fi&lt;/span&gt;
          &lt;span class="s"&gt;done&lt;/span&gt;

          &lt;span class="s"&gt;if [ ${#FUTURE_DATES[@]} -gt 0 ]; then&lt;/span&gt;
            &lt;span class="s"&gt;NEXT_DATE=$(printf "%s\n" "${FUTURE_DATES[@]}" | sort | head -n1)&lt;/span&gt;
            &lt;span class="s"&gt;echo "$NEXT_DATE" &amp;gt; next-build.txt&lt;/span&gt;
          &lt;span class="s"&gt;else&lt;/span&gt;
            &lt;span class="s"&gt;echo "none" &amp;gt; next-build.txt&lt;/span&gt;
          &lt;span class="s"&gt;fi&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Upload next build date&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/upload-artifact@v4&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;next-build&lt;/span&gt;
          &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;next-build.txt&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Workflow 2: Daily check and trigger
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Trigger Netlify build if today matches&lt;/span&gt;

&lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;schedule&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;cron&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;5&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;0&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;*&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;*&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;*'&lt;/span&gt;
  &lt;span class="na"&gt;workflow_dispatch&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;

&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;check-and-trigger&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;
    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/checkout@v4&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Download next build date&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/download-artifact@v4&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;next-build&lt;/span&gt;
          &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;.&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Trigger build if date matches&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
          &lt;span class="s"&gt;if [ ! -f next-build.txt ]; then&lt;/span&gt;
            &lt;span class="s"&gt;echo "No next-build.txt found"&lt;/span&gt;
            &lt;span class="s"&gt;exit 0&lt;/span&gt;
          &lt;span class="s"&gt;fi&lt;/span&gt;

          &lt;span class="s"&gt;NEXT=$(cat next-build.txt)&lt;/span&gt;
          &lt;span class="s"&gt;TODAY=$(date '+%Y-%m-%d')&lt;/span&gt;

          &lt;span class="s"&gt;if [ "$NEXT" == "none" ]; then&lt;/span&gt;
            &lt;span class="s"&gt;echo "No build scheduled."&lt;/span&gt;
            &lt;span class="s"&gt;exit 0&lt;/span&gt;
          &lt;span class="s"&gt;fi&lt;/span&gt;

          &lt;span class="s"&gt;if [ "$NEXT" == "$TODAY" ]; then&lt;/span&gt;
            &lt;span class="s"&gt;echo "✅ Triggering Netlify build for today."&lt;/span&gt;
            &lt;span class="s"&gt;curl -X POST -d '{}' "${{ secrets.NETLIFY_BUILD_HOOK }}"&lt;/span&gt;
          &lt;span class="s"&gt;else&lt;/span&gt;
            &lt;span class="s"&gt;echo "⏳ Not today. Next scheduled build is $NEXT."&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  🧾 Final result
&lt;/h2&gt;

&lt;p&gt;This setup ensures your Netlify site only rebuilds when a scheduled post becomes due. It:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;⚡ Avoids unnecessary builds or dummy commits&lt;/li&gt;
&lt;li&gt;🧠 Respects Netlify’s build time budget&lt;/li&gt;
&lt;li&gt;🧼 Keeps your repo clean and logic isolated&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;💡 This can be extended to multi-site, multi-branch setups, or even date queues using more advanced scheduling logic. But for a simple editorial workflow, it’s more than enough.&lt;/p&gt;

&lt;p&gt;Photo by &lt;a href="https://unsplash.com/fr/@agforl24?utm_content=creditCopyText&amp;amp;utm_medium=referral&amp;amp;utm_source=unsplash" rel="noopener noreferrer"&gt;Tai Bui&lt;/a&gt; on &lt;a href="https://unsplash.com/fr/photos/un-ecran-dordinateur-pose-sur-un-bureau-IMYU7kmPLwI?utm_content=creditCopyText&amp;amp;utm_medium=referral&amp;amp;utm_source=unsplash" rel="noopener noreferrer"&gt;Unsplash&lt;/a&gt;&lt;/p&gt;

</description>
      <category>netlify</category>
      <category>github</category>
      <category>automation</category>
      <category>ssg</category>
    </item>
    <item>
      <title>Vapid hosting on Heroku</title>
      <dc:creator>Thibault Milan</dc:creator>
      <pubDate>Tue, 23 Apr 2019 12:46:00 +0000</pubDate>
      <link>https://dev.to/clawfire/vapid-hosting-on-heroku-44oo</link>
      <guid>https://dev.to/clawfire/vapid-hosting-on-heroku-44oo</guid>
      <description>&lt;h4&gt;
  
  
  How to deploy a Vapid website on Heroku and configure the database, transfer your data but still have the file storage issue.
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F0%2AUBH0g-fFJ34PfFa1" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F0%2AUBH0g-fFJ34PfFa1" width="1024" height="683"&gt;&lt;/a&gt;Photo by &lt;a href="https://unsplash.com/@rezanamdari?utm_source=medium&amp;amp;utm_medium=referral" rel="noopener noreferrer"&gt;Reza Namdari&lt;/a&gt; on &lt;a href="https://unsplash.com?utm_source=medium&amp;amp;utm_medium=referral" rel="noopener noreferrer"&gt;Unsplash&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.vapid.com/" rel="noopener noreferrer"&gt;Vapid&lt;/a&gt; is a CMS that provide a dashboard to enter content, run with a lot of different kind of databases and let you do all of that from the HTML you are writing (thanks to &lt;a href="http://mustache.github.com" rel="noopener noreferrer"&gt;Mustache&lt;/a&gt;/&lt;a href="https://handlebarsjs.com/" rel="noopener noreferrer"&gt;Handlebars&lt;/a&gt; like syntax). It’s my new go for any little side project even if I have one main issue there: Going to production.&lt;/p&gt;

&lt;p&gt;Because Vapid is a node package that let you spaw a dev server and works on it but when it comes to production, you have the official paid service (starting at 7$/month/site) which support the dev of the software of course but seems a bit expensive when you compare to all the solutions you have nowadays: Now.sh, Heroku, AWS, …&lt;/p&gt;

&lt;p&gt;And since a lot of people are looking about how to deploy on those kinds of services, I gave it a try with Heroku. Here’s my journey.&lt;/p&gt;

&lt;h3&gt;
  
  
  Creating a new app
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyolpo76v3r1o5fbyix70.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyolpo76v3r1o5fbyix70.png" width="282" height="206"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let’s start by creating a new app, with the free tiers offered by the services.&lt;/p&gt;

&lt;p&gt;That’s enough to start deploying, but then I recommend to switch to a paid plan to keep your site running, otherwise it’s paused between activity period and takes time to boot up again).&lt;/p&gt;

&lt;p&gt;Once done, you should add a free &lt;em&gt;PostgreSQL&lt;/em&gt; add-on. Go into the &lt;em&gt;Ressources&lt;/em&gt; tab and search for postgres . Take &lt;em&gt;Heroku Postgres&lt;/em&gt; and choose the &lt;em&gt;Hobby Dev — free&lt;/em&gt; version.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Foxg7eazvgu9rw1juhmh3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Foxg7eazvgu9rw1juhmh3.png" width="800" height="354"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Preparing the vapid install
&lt;/h3&gt;

&lt;p&gt;Now, I assume you already have a vapid site locally made and just want to deploy it.&lt;/p&gt;

&lt;h4&gt;
  
  
  Editing the package.json file
&lt;/h4&gt;

&lt;p&gt;Since we’ll use &lt;em&gt;PostgreSQL&lt;/em&gt; we need to tell vapid that we are using something else than the default &lt;em&gt;SQLite&lt;/em&gt; database. And since it seems vapid check when starting we are installing the node packages for it (even if we don’t need it here) we’ll add it too.&lt;/p&gt;

&lt;p&gt;You should add the dialect config inside vapid section. And we’ll use the environment variable DATABASE_URL passed by default by Heroku to the application for connexion string.&lt;/p&gt;

&lt;p&gt;See the pg dependency? It’s the &lt;em&gt;PostgreSQL&lt;/em&gt; package I told you before. Sadly I didn’t find a way to get rid of it so far. I opened a bug on Vapid’s Github repo.&lt;/p&gt;

&lt;h4&gt;
  
  
  Deploying the app
&lt;/h4&gt;

&lt;p&gt;Heroku provide 3 deployment methods :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Using Heroku’s GIT&lt;/li&gt;
&lt;li&gt;Using Github&lt;/li&gt;
&lt;li&gt;Using a container registry&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I choose the first one because it’s basically just adding a Heroku remote to your project and you are free to push there whenever you want. Which is really convenient I find.&lt;/p&gt;

&lt;p&gt;I just have to run a git push heroku master and wait a few seconds. My app is now deployed and accessible to the public 🥳.&lt;/p&gt;

&lt;h3&gt;
  
  
  Optional: Importing your data
&lt;/h3&gt;

&lt;p&gt;Since I already have some data I input into my Vapid website and didn’t want to have to re-create everything here’s how I did:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Connect to SQLite and export data into several CSV files&lt;/li&gt;
&lt;li&gt;Connect to PostgreSQL and import my files&lt;/li&gt;
&lt;/ol&gt;

&lt;h4&gt;
  
  
  Exporting Data
&lt;/h4&gt;

&lt;p&gt;I’m on a Mac, so I look quickly on the internet and find an SQLite client with GUI called &lt;a href="https://sqlitebrowser.org/" rel="noopener noreferrer"&gt;DB Browser for SQLite&lt;/a&gt; which is free 💰.&lt;/p&gt;

&lt;p&gt;Open the data/vapid.sqlite and then browse each table and export them. I personally went for tableName.csv inside the same data folder. Just to keep organized.&lt;/p&gt;

&lt;h4&gt;
  
  
  Importing Data
&lt;/h4&gt;

&lt;p&gt;That’s a little bit trickier but, don’t panic. First, you have to visit your deployed website and create an admin account. It which build the dashboard and create the different tables into the DB.&lt;/p&gt;

&lt;p&gt;Go back on the Heroku admin panel of your app. Find the &lt;em&gt;Ressources&lt;/em&gt; tab. You should have your &lt;em&gt;Heroku Postgres&lt;/em&gt; add-on. Click on it to open, in a new window, the admin of this add-on.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwnncqff2dii7cthdz7d1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwnncqff2dii7cthdz7d1.png" width="800" height="280"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Into &lt;em&gt;Settings&lt;/em&gt; tab, you should find a &lt;em&gt;View Credentials…&lt;/em&gt; button. Click on it!&lt;/p&gt;

&lt;p&gt;At the point, I used &lt;a href="https://eggerapps.at/postico/" rel="noopener noreferrer"&gt;Postico&lt;/a&gt; which is shareware but works to import my data without having to pay for it. Using the credentials I connect to my Heroku DB and import my CSV files into each table of the PostgreSQL.&lt;/p&gt;

&lt;p&gt;That’s all 👍🏼&lt;/p&gt;

&lt;h3&gt;
  
  
  The elephant in the room
&lt;/h3&gt;

&lt;p&gt;Nope, I’m not gonna talk about PHP 😅 but fact that you can’t use image datatype with this method. Why? Because &lt;a href="https://help.heroku.com/K1PPS2WM/why-are-my-file-uploads-missing-deleted" rel="noopener noreferrer"&gt;the file storage is ephemeral in Heroku&lt;/a&gt;. That means each time your app is put in sleep, the file storage is deleted. In fact, your entire app is deleted until someone try to reach it again and then a new container is created and served. Your data into the DB are safe because the DB is not stored on that container but an independent, persistent, service.&lt;/p&gt;

&lt;p&gt;What to do then? Storing files on separate file storage seems a good way to go. Unfortunately Vapid doesn’t provide at that time some mechanism to be able to upload elsewhere the data. It shouldn’t be too difficult to do but if they want to be really open to everyone tastes, they will need to develop a connector method or rely on a third-party tool like they did for the database abstraction to be compatible with AWS S3 and other providers.&lt;/p&gt;

</description>
      <category>heroku</category>
      <category>postgres</category>
      <category>deployment</category>
      <category>webdev</category>
    </item>
    <item>
      <title>GDPR &amp; E-commerce</title>
      <dc:creator>Thibault Milan</dc:creator>
      <pubDate>Mon, 18 Jun 2018 11:38:06 +0000</pubDate>
      <link>https://dev.to/clawfire/gdpr-e-commerce-5e7d</link>
      <guid>https://dev.to/clawfire/gdpr-e-commerce-5e7d</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F0%2Aab5blEwlCPYftIXM" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F0%2Aab5blEwlCPYftIXM" width="1024" height="683"&gt;&lt;/a&gt;“A set of formal suits on hangers in a wardrobe” by &lt;a href="https://unsplash.com/@igorovsyannykov?utm_source=medium&amp;amp;utm_medium=referral" rel="noopener noreferrer"&gt;Igor Ovsyannykov&lt;/a&gt; on &lt;a href="https://unsplash.com?utm_source=medium&amp;amp;utm_medium=referral" rel="noopener noreferrer"&gt;Unsplash&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Just before starting, maybe all of us don’t know about GDPR yet (really ? You are part of the 0.1% of people that didn’t receive tons of emails about it then) and what’s it give as new rights to end-users.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The &lt;strong&gt;General Data Protection Regulation&lt;/strong&gt; ( &lt;strong&gt;GDPR&lt;/strong&gt; ) (EU) 2016/679 is a regulation in EU law on data protection and privacy for all individuals within the &lt;a href="https://en.wikipedia.org/wiki/European_Union" rel="noopener noreferrer"&gt;European Union&lt;/a&gt; (EU) and the &lt;a href="https://en.wikipedia.org/wiki/European_Economic_Area" rel="noopener noreferrer"&gt;European Economic Area&lt;/a&gt; (EEA). It also addresses the export of personal data outside the EU and EEA. The GDPR aims primarily to give control to citizens and residents over their personal data and to simplify the regulatory environment for international business by unifying the regulation within the EU.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://en.wikipedia.org/wiki/General_Data_Protection_Regulation" rel="noopener noreferrer"&gt;Wikipedia article on GDPR&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwktqhuxio2ocypulkox8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwktqhuxio2ocypulkox8.png" width="800" height="49"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So basicaly GDPR state few rules that are applied across all EU &amp;amp; EEA but also outside, since those rules needs to be followed by any company who handle EU &amp;amp; EAA people data. Either those people are customers, employees, contractors, visitors, leads, …&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1l9e772cqzazlfui3mg8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1l9e772cqzazlfui3mg8.png" width="800" height="713"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We can translate that to simpler statements :&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;You can’t share, without their consent, your customer’s data with 3rd party providers, partners &amp;amp; sponsors.&lt;/li&gt;
&lt;li&gt;You cannot add anyone to your marketing list&lt;/li&gt;
&lt;li&gt;You have to put on papers some plans about who is having access to client’s data, why, how and how you are ensuring the access are logged and revocable when the employee is leaving.&lt;/li&gt;
&lt;li&gt;You need to be able to give to the customers all their data (in a common portable format), erase, edit them or anonymize them on demand.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Following the GDPR, the ePrivacy evolve also in order to adapt to the new policies needed by GDPR and increasing the user’s protection. For exemple, we already see a lot of services that &lt;em&gt;require&lt;/em&gt; user to accept their new policy. That’s, fortunatly for the user, unlawfull.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;[…] access to services and functionalities must not be made conditional on the consent of a user to the processing of personal data or the processing of information related to or processed by the terminal equipment of end-users, meaning that cookie walls should be explicitly prohibited.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://edpb.europa.eu/sites/edpb/files/files/file1/edpb_statement_on_eprivacy_en.pdf" rel="noopener noreferrer"&gt;Read the full statement&lt;/a&gt; 🇺🇸&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fts15q1ujef8hkrhroohy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fts15q1ujef8hkrhroohy.png" width="800" height="49"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;There’s 2 main concept to keep in mind when collecting consent (because you need to, in order to use your user personal informations): Informed &amp;amp; Explicit.&lt;/p&gt;

&lt;p&gt;That mean you need to clearly inform your visitors &amp;amp; customers about which data exactly you will collect, how long you will keep it, how they can access/edit/export or ask for complete erasure.&lt;/p&gt;

&lt;p&gt;To help you understand better the consequences of GDPR (or previous laws) on online retail, we made a small chart right after. You can see what you can’t do (orange), what you may kind (yellow) but subject to prerequisites, and what you absolutely can do (green).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1ldlpj4vkkgnw0p80iz9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1ldlpj4vkkgnw0p80iz9.png" width="800" height="543"&gt;&lt;/a&gt;The do and don’t of e-commerce marketing following GDPR.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;em&gt;Retargeting&lt;/em&gt; is only allowed if you collected the explicit consent from the customer to receive this kind of emails. Retargeting can be made by email or ad platform, but the technical solution has no impact on the need to require the user’s consent.&lt;/li&gt;
&lt;li&gt;That’s a tricky question, and I have no clue about this one. Empty cart emails is marketing emails, for sure, but it’s also based on the behaviours of the end-user, and to &lt;em&gt;force&lt;/em&gt; him to close a deal he pause. Even if it’s a well-known sales technique, sometimes followed by a coupon as incentive, I wouldn’t advice to continue using it before more clarification by experts.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Product you may like&lt;/em&gt; features are ok to use, without consent, if you are only using some cross-selling or up-selling functionalities that are not based on the user behaviour.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Marketing emails&lt;/em&gt; are allowed to your newsletter users if they give you their consent to do so. Otherwise, only past customers can be targeted.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fo7puzd6v2t9glo5tob3v.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fo7puzd6v2t9glo5tob3v.png" width="800" height="49"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As we can seen just before, mailing campaign can be sent to people who :&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Subscribe to your mailing list. And you’ll need to be able to prove they add subscribe to it.&lt;/li&gt;
&lt;li&gt;People who bought stuff from you. It falls under what is called &lt;em&gt;soft opt-in&lt;/em&gt; . You need to provide an unsubscribe link &lt;em&gt;in every email&lt;/em&gt; then.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;For those 2 categories of people, no need to bother them asking if they can confirm their subscriptions. For the others, … well. You are not legally supposed to have other kind of people in your emailing database. The law already prohibit you to add people who just sent you email or handle you business cards.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Firz7n503f9iq1knwrheo.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Firz7n503f9iq1knwrheo.png" width="800" height="49"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;There’s also another “issue” with GDPR, regarding your 3rd party provider. Since you may have choose a SaaS solution like Shopify, you will have to do extra steps in order to be compliant with GDPR :&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;You will have to be sure the provider you choose is GDPR compliant, because you are the one who is accountable for that.&lt;/li&gt;
&lt;li&gt;You will need to be sure the provider will give you all the possibilities required by law in term of data manipulation (send to the user all the data you have on him, delete all those data, …).&lt;/li&gt;
&lt;li&gt;You’ll not be able to hide behind your 3rd party solution provider in case of data loss / leak. And that’s mostly not the fault of GDPR but of the new addendum (usually a D.P.A : Data Processing Agreement) your provider may have already sent to you and require you to sign. So be carefull about the fine lines.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://gdprhallofshame.com/" rel="noopener noreferrer"&gt;GDPR Hall of Shame&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fio4rzq64nv1dp4hnry6n.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fio4rzq64nv1dp4hnry6n.png" width="800" height="49"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The subject of GDPR is quite extensive, and we just cover a small part of it, the one that is related to the online-retail industry. But GDPR impact all business, small or big, non-profits and gouvernment, and not just with their customers but also their employees.&lt;/p&gt;

&lt;p&gt;If you want to go further, here’s a small collection of ressources to start with.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://cst.cnpd.lu/portal/" rel="noopener noreferrer"&gt;GDPR Compliance support tool&lt;/a&gt; 🇺🇸, an online step by step guide to self assess your alignment with GDPR regulation&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.shopify.com/blog/gdpr-ecommerce" rel="noopener noreferrer"&gt;GDPR: What You (And Your Store) Need to Know About This New Law&lt;/a&gt; 🇺🇸&lt;/li&gt;
&lt;li&gt;
&lt;a href="http://www.gondola.be/fr/news/retail/limpact-du-gdpr-sur-le-retail" rel="noopener noreferrer"&gt;L’impact du GDPR sur le retail - Gondola&lt;/a&gt; 🇫🇷&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://cnpd.public.lu/fr/dossiers-thematiques/Reglement-general-sur-la-protection-des-donnees/responsabilite-accrue-des-responsables-du-traitement/guide-preparation-rgpd.html" rel="noopener noreferrer"&gt;Guide de préparation au nouveau règlement général sur la protection des données - CNPD&lt;/a&gt; 🇫🇷&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://en.wikipedia.org/wiki/General_Data_Protection_Regulation" rel="noopener noreferrer"&gt;Wikipedia Entry about GDPR&lt;/a&gt; 🇺🇸&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://edpb.europa.eu/sites/edpb/files/files/file1/edpb_statement_on_eprivacy_en.pdf" rel="noopener noreferrer"&gt;Revision of the ePrivacy Regulation and its impact on the protection of individuals with regard to the privacy and confidentiality of their communications&lt;/a&gt; 🇺🇸&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Thanks for reading ! If you want more informations about GDPR, don’t hesitate to heads to &lt;a href="http://smile.eu" rel="noopener noreferrer"&gt;smile.eu&lt;/a&gt; . We also publish a fortnightly technology watch newsletter, you can &lt;a href="https://www.getrevue.co/profile/smileinnovation" rel="noopener noreferrer"&gt;take a look at it online&lt;/a&gt; &amp;amp; subscribe !&lt;/p&gt;

&lt;p&gt;You can find me on &lt;a href="https://twitter.com/thibaultmilan" rel="noopener noreferrer"&gt;Twitter&lt;/a&gt;, &lt;a href="https://www.linkedin.com/in/thibaultmilan/" rel="noopener noreferrer"&gt;Linkedin&lt;/a&gt;, &lt;a href="https://www.getrevue.co/profile/thibault" rel="noopener noreferrer"&gt;my newsletter&lt;/a&gt; &amp;amp; &lt;a href="http://thibaultmilan.com/" rel="noopener noreferrer"&gt;my website&lt;/a&gt;.&lt;/p&gt;




</description>
      <category>customerdata</category>
      <category>marketing</category>
      <category>retail</category>
      <category>gdpr</category>
    </item>
    <item>
      <title>KPMG Luxembourg is hiring frontend &amp; backend developer</title>
      <dc:creator>Thibault Milan</dc:creator>
      <pubDate>Tue, 14 Nov 2017 14:11:15 +0000</pubDate>
      <link>https://dev.to/clawfire/kpmg-luxembourg-is-hiring-frontend--backend-developer-9jp</link>
      <guid>https://dev.to/clawfire/kpmg-luxembourg-is-hiring-frontend--backend-developer-9jp</guid>
      <description>&lt;h1&gt;
  
  
  Who where are
&lt;/h1&gt;

&lt;p&gt;KPMG Luxembourg is an Audit &amp;amp; Tax (&amp;amp; consulting) Big4. We are more than 1700 people based in Luxembourg, mostly doing other things than IT but people understood that highlighting batch of 5000 pages of papers has no tomorrow and they need to take the IT transformation seriously. And yes, they should have been done that years ago. But better now than never right?&lt;/p&gt;

&lt;p&gt;My department is Tech, Data &amp;amp; Analytics and we're developing web &amp;amp; mobile application so support either our own need either clients ones. We also educate the other members of the firm to change their mind and sell SaaS and not just tailor made development.&lt;/p&gt;

&lt;h1&gt;
  
  
  What we are looking for
&lt;/h1&gt;

&lt;p&gt;For both profiles (or mixed one) a knowledge of Agile Development and &lt;strong&gt;2 years of XP at least is a must&lt;/strong&gt;. If you could show some past project or at least talk about it, it will be a plus indeed. We assume that you already have knowledge about basic &lt;strong&gt;HTML&lt;/strong&gt; &amp;amp; &lt;strong&gt;Semantic&lt;/strong&gt; (like in Semantic HTML, even if, yes, we use Semantic UI ðŸ˜), &lt;strong&gt;GIT&lt;/strong&gt;, and Project tracking tools (we use &lt;strong&gt;Phabricator&lt;/strong&gt; &amp;amp; &lt;strong&gt;Gitlab&lt;/strong&gt;).&lt;/p&gt;

&lt;h2&gt;
  
  
  Frontend
&lt;/h2&gt;

&lt;p&gt;Developer with experience in reactJS development, sensibility for UX.&lt;/p&gt;

&lt;h2&gt;
  
  
  Backend
&lt;/h2&gt;

&lt;p&gt;Developer with experience in Play Scala, web service oriented architecture, cloud architecture oriented development. &lt;/p&gt;

&lt;h1&gt;
  
  
  What we offer
&lt;/h1&gt;

&lt;p&gt;13 month income&lt;br&gt;
+ ðŸ’¶ bonus (50% on performance of company - 50% on your performance)&lt;br&gt;
+ ðŸšŒðŸšƒðŸšˆunlimited public transportation for 60â‚¬ / years&lt;br&gt;
+ ðŸ‹ðŸ»”â™‚ï¸conciergerie &amp;amp; access to gym (free)&lt;br&gt;
+ ðŸ§“ðŸ¼pension, insurance &amp;amp; ðŸ¦banking advantage&lt;br&gt;
+ ðŸš—very competitive leasing car catalog&lt;br&gt;
+ ðŸ‘©ðŸ¼”ðŸ«budget for training &amp;amp; conferences&lt;/p&gt;

&lt;h1&gt;
  
  
  How to apply
&lt;/h1&gt;

&lt;p&gt;You can apply online on &lt;a href="http://kpmg.lu/careers" rel="noopener noreferrer"&gt;our job website&lt;/a&gt; or just write to me &lt;a href="//mailto:thibault.milan@kpmg.lu?subject=My%20Resume"&gt;thibault.milan@kpmg.lu&lt;/a&gt; with your resume and I'll be sure we review it with our team and follow with HR (the other way around may take times sometimes ðŸ¤¨) &lt;/p&gt;

</description>
      <category>hiring</category>
      <category>luxembourg</category>
      <category>react</category>
      <category>scala</category>
    </item>
    <item>
      <title>Updating Attendize</title>
      <dc:creator>Thibault Milan</dc:creator>
      <pubDate>Thu, 19 Jan 2017 15:34:05 +0000</pubDate>
      <link>https://dev.to/clawfire/updating-attendize-4k7c</link>
      <guid>https://dev.to/clawfire/updating-attendize-4k7c</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxk4wn6uvevoxautwlbpp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxk4wn6uvevoxautwlbpp.png" width="800" height="391"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I’m using the super duper &lt;a href="http://attendize.com" rel="noopener noreferrer"&gt;Attendize&lt;/a&gt;, a open-source ticketing system, for some of my activities. After having hard time to get it work, I found nearly 0 documentation about how to update it.&lt;/p&gt;

&lt;p&gt;Fortunately, as it’s an open-source software, I was able to open an issue and ask the developer community around this software how to do it.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/Attendize/Attendize/issues/285#issuecomment-272705469" rel="noopener noreferrer"&gt;Update procedure · Issue #285 · Attendize/Attendize&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So, in order to update your installation you have to :&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Copy over files with the newer version (via SFTP)&lt;/li&gt;
&lt;li&gt;Log-in with &lt;code&gt;ssh&lt;/code&gt; to your server and enter &lt;code&gt;php artisan migrate&lt;/code&gt; into the root folder to launch the database migration.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;That’s it 🙌🏼.&lt;/p&gt;

&lt;p&gt;I’m a little bit concerned about the FTP / SSH thing in 2017 so I’m gonna look to a better way to do it, with some CI tools to automate the file deployment and command running to migrate DB. Keep you posted 😉&lt;/p&gt;




</description>
      <category>ci</category>
      <category>automation</category>
      <category>laravel</category>
      <category>php</category>
    </item>
    <item>
      <title>Fixing homebrew on macOS Sierra</title>
      <dc:creator>Thibault Milan</dc:creator>
      <pubDate>Sun, 07 Aug 2016 10:40:17 +0000</pubDate>
      <link>https://dev.to/clawfire/fixing-homebrew-on-macos-sierra-4p9o</link>
      <guid>https://dev.to/clawfire/fixing-homebrew-on-macos-sierra-4p9o</guid>
      <description>&lt;p&gt;Une nouvelle version de macOS (bye bye os X au passage) viens forcément tout exploser au niveau de homebrew. Comme toujours. Sans compter que si, comme moi, vous n’aviez pas encore déplacer vos casks depuis &lt;code&gt;/opt/homebrew-cask/&lt;/code&gt; vers &lt;code&gt;/usr/local/Caskroom/&lt;/code&gt; cela va nécessiter une petite étape supplémentaire apparemment dû à une restriction des droits sur &lt;code&gt;/usr/local/&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbbxh4ceqxlhzr7qrot3s.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbbxh4ceqxlhzr7qrot3s.png" width="586" height="354"&gt;&lt;/a&gt;/ Bye bye os. X&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 1 : Mettre à jour homebrew
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;brew update
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 2 : Fixer les droits &amp;amp; réinstaller les build tools
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo chown -R $(whoami) /usr/local
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A ce moment là vous pouvez aussi vérifier que &lt;em&gt;brew doctor&lt;/em&gt; ne vous retourne rien de mauvais. Ensuite il faut réinstaller les build tool natifs de macOS :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;xcode-select --install
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 3 : Bouger vos casks dans le nouveau répertoire
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mv /opt/homebrew-cask/Caskroom/* /usr/local/Caskroom/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ensuite vous pouvez virer l’ancien dossier sans remords :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;rmdir /opt/homebrew-cask/Caskroom
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Et voila ! Vous pouvez installer sans aucun soucis vos cask et les mettre à jour. Un petit coup de brew upgrade pour la route et vous êtes bon 😉&lt;/p&gt;




</description>
      <category>homebrew</category>
      <category>macos</category>
      <category>french</category>
    </item>
  </channel>
</rss>
