<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:media="http://search.yahoo.com/mrss/"><channel><title><![CDATA[Get Blogged by JoKi]]></title><description><![CDATA[The only frontiers are in your mind]]></description><link>https://jochen.kirstaetter.name/</link><image><url>https://jochen.kirstaetter.name/favicon.png</url><title>Get Blogged by JoKi</title><link>https://jochen.kirstaetter.name/</link></image><generator>Ghost 3.42</generator><lastBuildDate>Fri, 17 Apr 2026 05:20:11 GMT</lastBuildDate><atom:link href="https://jochen.kirstaetter.name/rss/" rel="self" type="application/rss+xml"/><ttl>60</ttl><item><title><![CDATA[Gemma 3 - missing features despite announcement]]></title><description><![CDATA[<p>Congrats to the team to provide the new Gemma 3 models and the new endpoint on the Google AI API. The announcement blog - <a href="https://blog.google/technology/developers/gemma-3/">https://blog.google/technology/developers/gemma-3/</a> - reads wonderfully. Until someone puts it to the test...</p><h2 id="create-ai-with-advanced-text-and-visual-reasoning-capabilities">Create AI with advanced text and visual reasoning capabilities</h2><p>Easily</p>]]></description><link>https://jochen.kirstaetter.name/gemma-3-missing-features-despite-announcement/</link><guid isPermaLink="false">67e233b68b060f271554682f</guid><category><![CDATA[Development]]></category><dc:creator><![CDATA[Jochen Kirstätter]]></dc:creator><pubDate>Wed, 12 Mar 2025 04:45:00 GMT</pubDate><media:content url="https://jochen.kirstaetter.name/content/images/2025/03/Gemma3.png" medium="image"/><content:encoded><![CDATA[<img src="https://jochen.kirstaetter.name/content/images/2025/03/Gemma3.png" alt="Gemma 3 - missing features despite announcement"><p>Congrats to the team to provide the new Gemma 3 models and the new endpoint on the Google AI API. The announcement blog - <a href="https://blog.google/technology/developers/gemma-3/">https://blog.google/technology/developers/gemma-3/</a> - reads wonderfully. Until someone puts it to the test...</p><h2 id="create-ai-with-advanced-text-and-visual-reasoning-capabilities">Create AI with advanced text and visual reasoning capabilities</h2><p>Easily build applications that analyze images, text, and short videos, opening up new possibilities for interactive and intelligent applications</p><p>HTTP 400: "Image input modality is not enabled for models/gemma-3-27b-it"<br>HTTP 400: "Audio input modality is not enabled for models/gemma-3-27b-it"</p><p>Tried different images (png, jpg, bmp), video (mp4) and PDF documents - both via <code>inlineData</code> and per File API using <code>fileData</code> attributes.</p><h2 id="create-ai-driven-workflows-using-function-calling">Create AI-driven workflows using function calling</h2><p>Gemma 3 supports function calling and structured output to help you automate tasks and build agentic experiences.</p><p>HTTP 400: "Function calling is not enabled for models/gemma-3-27b-it"<br>HTTP 400: "Json mode is not enabled for models/gemma-3-27b-it"<br>HTTP 400: "Enum mode is not enabled for models/gemma-3-27b-it"</p><h2 id="system-instruction">System Instruction</h2><p>HTTP 400: "Developer instruction is not enabled for models/gemma-3-27b-it"</p><h2 id="code-execution">Code execution?</h2><p>It's not explicitly mentioned in the blog. What's the situation here? Right now...</p><p>HTTP 400: "Code execution is not enabled for models/gemma-3-27b-it"</p><h2 id="candidate-count-1">Candidate count &gt; 1?</h2><p>It's not explicitly mentioned in the blog. What's the situation here? Right now...</p><p>HTTP: "Multiple candidates is not enabled for models/gemma-3-27b-it"</p><p>Not sure what's the issue is...</p><p>However, with the announcement blog I would kind of expect that the mentioned features are available and operational from day 0 on. And not hoping for the best and then those are being added at a later stage.</p><p>I'm not sure whether those features have been disabled for the gemma3 model in the Gemini API and the model itself might be capable to deal with everything, like when used locally or deployed in Vertex AI or Cloud Run with GPU...</p><p>What are your observations?</p>]]></content:encoded></item><item><title><![CDATA[Gemini ResponseSchema vs JSON Schema specs of "type" as array]]></title><description><![CDATA[<p>Recently, while developing some changes in the Gemini SDK for .NET and given a reported issue on GitHub I had a look at the possibilities of passing an object as the expected structured output in JSON format in order to get the response from the Gemini API.</p><p>Turns out it's</p>]]></description><link>https://jochen.kirstaetter.name/gemini-responseschema/</link><guid isPermaLink="false">678de5a78b060f27155466d7</guid><category><![CDATA[Development]]></category><dc:creator><![CDATA[Jochen Kirstätter]]></dc:creator><pubDate>Mon, 20 Jan 2025 07:10:08 GMT</pubDate><media:content url="https://jochen.kirstaetter.name/content/images/2025/01/Snapshot_2025-01-20_11-02-42.png" medium="image"/><content:encoded><![CDATA[<img src="https://jochen.kirstaetter.name/content/images/2025/01/Snapshot_2025-01-20_11-02-42.png" alt="Gemini ResponseSchema vs JSON Schema specs of "type" as array"><p>Recently, while developing some changes in the Gemini SDK for .NET and given a reported issue on GitHub I had a look at the possibilities of passing an object as the expected structured output in JSON format in order to get the response from the Gemini API.</p><p>Turns out it's not trivial and there are several options available, each with of their own obstacles. Let's have a look...</p><h2 id="json-schema-exporter-in-net-9">JSON schema exporter in .NET 9</h2><p>First, I came across a new feature in .NET 9 - <a href="https://learn.microsoft.com/en-us/dotnet/standard/serialization/system-text-json/extract-schema">JSON schema exporter</a>.</p><blockquote>The <a href="https://learn.microsoft.com/en-us/dotnet/api/system.text.json.schema.jsonschemaexporter">JsonSchemaExporter</a> class, introduced in .NET 9, lets you extract <a href="https://json-schema.org/">JSON schema</a> documents from .NET types using either a <a href="https://learn.microsoft.com/en-us/dotnet/api/system.text.json.jsonserializeroptions">JsonSerializerOptions</a> or <a href="https://learn.microsoft.com/en-us/dotnet/api/system.text.json.serialization.metadata.jsontypeinfo">JsonTypeInfo</a> instance. The resultant schema provides a specification of the JSON serialization contract for the .NET type. The schema describes the shape of what would be serialized and what can be deserialized.</blockquote><p>Although interesting, it's too new and the Gemini SDK for .NET needs support for previous versions of .NET including .NET Framework. So, not an option yet.</p><h2 id="njsonschema-by-rico-suter">NJsonSchema by Rico Suter</h2><p>Next, I found the <a href="https://github.com/RicoSuter/NJsonSchema">NJsonSchema</a> library and gave it a try. The library is well written and actively maintained. Also, the package supports .NET Framework 4.6.2 or higher, .NET Standard 2.0, and .NET 6.0 or higher. Sounds like the perfect candidate to integrate into my SDK. </p><p>However, I noticed that there are slight differences between the available documentation and the latest version 11.x of the NuGet package. Using the previous, latest version 10.x of the package solved that.</p><p>Unfortunately, I ran into the problem described below regarding the generation of `type` keys as arrays of principle types, and I couldn't find a solution to output a single string value (as expected by the Gemini API).</p><p>The latest version seems to migrate from `Newtonsoft.Json` to `System.Text.Json` but that process has not been completed yet. Throughout the Gemini SDK for .NET I'm using `System.Text.Json` everywhere as much as possible. I think the test projects still use `Newtonsoft.Json`indirectly somehow. Anyway, I didn't like adding another JSON library to the SDK and I couldn't resolve the described issue with the `type` array, so not an option.</p><h2 id="json-everything-by-greg-dennis">json-everything by Greg Dennis</h2><p>Lastly, I came across the <a href="https://github.com/json-everything/json-everything">json-everything</a> library which generated the JSON schema as expected by the Gemini API. The NuGet package is compatible with .NET Standard 2.0 (which works for .NET Framework 4.7.1 or higher, IIRC) as well as .NET 8.0 or higher. As I ditched support for .NET 6.0 recently in the SDK it's a match.</p><h2 id="serialization-of-net-types-to-json-and-json">Serialization of .NET types to JSON and JSON</h2><p>Yes, you read this correctly. Most commonly the Gemini SDK for .NET has to serialize the payload for the REST API endpoint requests. That's regular stuff and nothing special about it using `System.Text.Json`. </p><figure class="kg-card kg-code-card"><pre><code class="language-csharp">/// &lt;summary&gt;
/// Return serialized JSON string of request payload.
/// &lt;/summary&gt;
/// &lt;param name="request"&gt;&lt;/param&gt;
/// &lt;returns&gt;&lt;/returns&gt;
protected string Serialize&lt;T&gt;(T request)
{
	return JsonSerializer.Serialize(request, _options);
}</code></pre><figcaption>The "usual" method to serialize to JSON in .NET</figcaption></figure><p>However, to generate a structured output one has to provide a JSON Schema describing the object used for the response. JSON schema uses a defined syntax to describe objects which is different from a regular object serialization. Hence the need to integrate one of the previously mentioned libraries in order to be generate a JSON schema based on a .NET type.</p><p>One of the solutions is to implement a specialized JSON converter and attribute the property to use it. Here's how it's done in the SDK.</p><figure class="kg-card kg-code-card"><pre><code class="language-csharp">/// &lt;summary&gt;
/// Optional. Output response schema of the generated candidate text when response mime type can have schema.
/// &lt;/summary&gt;
/// &lt;remarks&gt;
/// Schema can be objects, primitives or arrays and is a subset of [OpenAPI schema](https://spec.openapis.org/oas/v3.0.3#schema).
/// If set, a compatible response_mime_type must also be set. Compatible mimetypes: `application/json`: Schema for JSON response.
/// &lt;/remarks&gt;
[JsonConverter(typeof(ResponseSchemaJsonConverter))]
public object? ResponseSchema { get; set; }</code></pre><figcaption>Assign a custom JSON converter to the property</figcaption></figure><p>A custom converter needs to overwrite two methods - Read and Write. See further details about <a href="https://learn.microsoft.com/en-us/dotnet/standard/serialization/system-text-json/converters-how-to">How to write custom converters for JSON serialization (marshalling) in .NET</a>. Here's the current implementation (kindly ignore Read as its not used).</p><figure class="kg-card kg-code-card"><pre><code class="language-csharp">#if NET472_OR_GREATER || NETSTANDARD2_0
using System;
using System.Text.Json;
using System.Text.Json.Serialization;
#endif
using Json.Schema;
using Json.Schema.Generation;

namespace Mscc.GenerativeAI
{
    /// &lt;summary&gt;
    /// Custom JSON converter to serialize and deserialize JSON schema.
    /// &lt;/summary&gt;
    public sealed class ResponseSchemaJsonConverter : JsonConverter&lt;object&gt;
    {
        /// &lt;inheritdoc cref="JsonConverter"/&gt;
        public override object? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
        {
            return JsonSerializer.Deserialize&lt;dynamic&gt;(reader.GetString()!, options);
        }

        /// &lt;inheritdoc cref="JsonConverter"/&gt;
        public override void Write(
            Utf8JsonWriter writer,
            object value,
            JsonSerializerOptions options)
        {
            var type = value.GetType();
            // How to figure out: type vs anonymous vs dynamic?
            if (type.Name.Substring(0,Math.Min(type.Name.Length, 20)).Contains("AnonymousType"))
            {
                var newOptions = new JsonSerializerOptions(options);
                newOptions.Converters.Remove(this);
                JsonSerializer.Serialize(writer, value, value.GetType(), newOptions);
            }
            else
            {
                var config = new SchemaGeneratorConfiguration()
                {
                    PropertyNameResolver = PropertyNameResolvers.CamelCase
                };
                var schemaBuilder = new JsonSchemaBuilder();
                var schema = schemaBuilder.FromType(type, config).Build();
                JsonSerializer.Serialize(writer, schema, schema.GetType(), options);
            }
        }
    }
}</code></pre><figcaption>Custom JSON Converter class to generate JSON schema output</figcaption></figure><p>As you see, there's still of room to improve the implementation. For once, I'm struggling with the serialization of types from the `System.Dynamic` namespace, eg. ExpandoObject. Why? Because this generates (again) additional JSON keys like `readOnly` which are rejected. Right now, it's not clear to me whether it's a specs problem against JSON Schema or an incompatibility on the side of the Gemini API. </p><p><em>Note: The boolean keywords `readOnly`and `writeOnly` are part of the <a href="https://json-schema.org/understanding-json-schema/reference/annotations">JSON Schema Annotations</a> and have been added in draft 7.</em></p><p>Feel free to drop a note or hint in the article comments below. Or create a PR in the repository on GitHub.</p><p>Following is the post I published on the <a href="https://discuss.ai.google.dev/t/responseschema-and-json-schema-specs-of-type-as-array/61211">Build with Google AI Forum</a>:</p><h2 id="incompatibility-issue-in-the-gemini-api-regarding-json-schema">Incompatibility issue in the Gemini API regarding JSON Schema</h2><p>I'm facing an issue regarding the generation of JSON Schema used as value of <code>GenerationConfig.ResponseSchema</code> given the following scenario. The class is defined like this</p><pre><code>class Recipe {
    public string Name { get; set; }
}
</code></pre><p>Which is then passed into the property as a list / array in order to retrieve multiple suggestions from the Gemini API.</p><pre><code>var generationConfig = new GenerationConfig()
{
    ResponseMimeType = "application/json",
    ResponseSchema = new List&lt;Recipe&gt;()
};
</code></pre><p>The generated output looks like this</p><pre><code>{
  "model" : "models/gemini-1.5-pro-latest",
  "contents" : [ {
    "role" : "user",
    "parts" : [ {
      "text" : "List a few popular cookie recipes."
    } ]
  } ],
  "generationConfig" : {
    "responseMimeType" : "application/json",
    "responseSchema" : {
      "type" : "array",
      "items" : {
        "type" : "object",
        "properties" : {
          "name" : {
            "type" : [ "string", "null" ]
          }
        },
        "required" : [ "name" ]
      }
    }
  }
}
</code></pre><p>Specifying the property <code>Name</code> as a <strong>nullable string</strong>. This is conform with the specs of <code>type</code> according to <a href="https://json-schema.org/understanding-json-schema/reference/type">https://json-schema.org/understanding-json-schema/reference/type</a> allowing  <em>instances that can be of multiple primitive types</em>.</p><p><em>The type keyword may either be a string or an array:</em><br>**     If it's a string, it is the name of one of the basic types above.*<br>**     If it is an array, it must be an array of strings, where each string is the name of one of the basic types, and each element is unique. In this case, the JSON snippet is valid if it matches any of the given types.*</p><p>See also <a href="https://json-schema.org/draft/2020-12/json-schema-core#section-7.6.1">https://json-schema.org/draft/2020-12/json-schema-core#section-7.6.1</a> and following paragraphs.</p><p>Currently, the Gemini API returns an HTTP 400 Bad Request with this information.</p><pre><code>{
  "error": {
    "code": 400,
    "message": "Invalid JSON payload received. Unknown name \"type\" at 'generation_config.response_schema.items.properties[0].value': Proto field is not repeating, cannot start list.\nInvalid JSON payload received. Unknown name \"type\" at 'generation_config.response_schema.items.properties[1].value': Proto field is not repeating, cannot start list.",
    "status": "INVALID_ARGUMENT",
    "details": [
      {
        "@type": "type.googleapis.com/google.rpc.BadRequest",
        "fieldViolations": [
          {
            "field": "generation_config.response_schema.items.properties[0].value",
            "description": "Invalid JSON payload received. Unknown name \"type\" at 'generation_config.response_schema.items.properties[0].value': Proto field is not repeating, cannot start list."
          },
          {
            "field": "generation_config.response_schema.items.properties[1].value",
            "description": "Invalid JSON payload received. Unknown name \"type\" at 'generation_config.response_schema.items.properties[1].value': Proto field is not repeating, cannot start list."
          }
        ]
      }
    ]
  }
}
</code></pre><p>The error message essentially showing <strong>"type": Proto field is not repeating, cannot start list.</strong></p><p>And therefor indicating that the value of <code>type</code> cannot be a list/array of primitives types.</p><p>Adding to this observation on the API side, using the same response schema in AIS gives me the following error message on Save.</p><figure class="kg-card kg-image-card"><img src="https://jochen.kirstaetter.name/content/images/2025/01/4b0c3a7b76ce041d4a05c14bf642a2bdc0a85de4_2_690x162.png" class="kg-image" alt="Gemini ResponseSchema vs JSON Schema specs of "type" as array" srcset="https://jochen.kirstaetter.name/content/images/size/w600/2025/01/4b0c3a7b76ce041d4a05c14bf642a2bdc0a85de4_2_690x162.png 600w, https://jochen.kirstaetter.name/content/images/2025/01/4b0c3a7b76ce041d4a05c14bf642a2bdc0a85de4_2_690x162.png 690w"></figure><p>Sorry to say but this seems to be a short-coming on Gemini's side regarding the interpretation of JSON Schema specifications.</p><p>Similarly, I'm getting HTTP 400 Bad Request responses when other keys, like eg. "readOnly" and others are used in the schema definition.</p><p>This doesn't align with the specs of JSON Schema.</p><p>Changing the type value to a single primitive type returns an HTTP 200 OK.</p><pre><code>{
  "model" : "models/gemini-1.5-pro-latest",
  "contents" : [ {
    "role" : "user",
    "parts" : [ {
      "text" : "List a few popular cookie recipes."
    } ]
  } ],
  "generationConfig" : {
    "responseMimeType" : "application/json",
    "responseSchema" : {
      "type" : "array",
      "items" : {
        "type" : "object",
        "properties" : {
          "name" : {
            "type" : "string"
          }
        }
      }
    }
  }
}
</code></pre><p>and the result as expected.</p><pre><code>{
  "candidates" : [ {
    "content" : {
      "parts" : [ {
        "text" : "[{\"name\": \"Chocolate Chip Cookies\"}, {\"name\": \"Peanut Butter Cookies\"}, {\"name\": \"Oatmeal Raisin Cookies\"}, {\"name\": \"Snickerdoodles\"}, {\"name\": \"Shortbread Cookies\"}]"
      } ],
      "role" : "model"
    },
    "finishReason" : "STOP",
    "avgLogprobs" : -0.009499770402908326
  } ],
  "usageMetadata" : {
    "promptTokenCount" : 8,
    "candidatesTokenCount" : 45,
    "totalTokenCount" : 53
  },
  "modelVersion" : "gemini-1.5-pro-002"
}
</code></pre><p>Someone else observing this issue?<br>Right now, this seems to be an issue with the Gemini API not accepting a conforming JSON Schema with multiple primitive types as the <code>type</code> definition of a property.</p><p>Assistance please. Thanks.</p><!--kg-card-begin: html--><small>Image courtesy of Jochen Kirst&auml;tter</small><!--kg-card-end: html-->]]></content:encoded></item><item><title><![CDATA[C# Corner Annual Conference 2017]]></title><description><![CDATA[Speaking at the C# Conference 2017 in Delhi was an amazing experience. Both, the event and the exploration of Delhi. Visiting the Taj Mahal was a highlight.]]></description><link>https://jochen.kirstaetter.name/c-corner-conference-2017/</link><guid isPermaLink="false">5a780fcfe929b423b2ad19bf</guid><category><![CDATA[Community]]></category><category><![CDATA[Personal]]></category><dc:creator><![CDATA[Jochen Kirstätter]]></dc:creator><pubDate>Thu, 30 May 2024 09:00:00 GMT</pubDate><media:content url="https://jochen.kirstaetter.name/content/images/2024/05/17796494_1503202119690423_6013537920441171383_n.jpg" medium="image"/><content:encoded><![CDATA[<img src="https://jochen.kirstaetter.name/content/images/2024/05/17796494_1503202119690423_6013537920441171383_n.jpg" alt="C# Corner Annual Conference 2017"><p>Recently I have been watching the travel documentary "James May, our man in India". One of the episodes, in particular #2, while he is visiting Delhi and Agra, it hit a chord in my memories. Time to write about my trip to India and speaking at the C# Corner Annual Conference 2017.</p><!--kg-card-begin: markdown--><p><a href="http://www.c-sharpcorner.com/news/c-sharp-corner-annual-conference-2017-official-recap">C# Corner Annual Conference 2017</a>, Delhi<br>
(the link might probably not work anymore)</p>
<!--kg-card-end: markdown--><p>It all started during 2016 when the founder of C# Corner <a href="https://www.linkedin.com/in/mchand">Mahesh Chand</a> invited me to come to and speak at the conference in 2016 already. Unfortunately, it was a quite short-noticed call and I had bookings for business scheduled already. Then, about the end of December fellow MVP and MSCC community member <a href="https://mu.linkedin.com/in/chervinebhiwoo">Chervine Bhiwoo</a> sent me an email to check my Inbox for a potential speaking engagement with C# Corner Conference 2017. And indeed in early January Praveen Kumar and I had some conversation about potential submissions. We quickly agreed on the title of the talk and the rest was all about travel preparations.</p><h2 id="travelling-to-india">Travelling to India</h2><p>Whether you are Mauritian or not like in my case, India seems to ask quite a number of citizens to apply for a VISA to enter the country. The application process can be initiated online easily. For the actual VISA I went to the High Commission in Port Louis to pay the fees, drop off my passport and collect it after a week or so. The officer at the High Commission was very forth coming and friendly. Overall a pleasant experience to obtain a VISA for India.</p><p><em>Note:</em> The fees for a VISA depend on your citizenship; Mauritians pay less than what I paid for.</p><p>For the arrangements for air travel there are multiple options available. Among them are flights on Air Mauritius, Air India, Emirates and others. I do not recall whether there is a direct flight between Delhi and Mauritius though. Probably yes but limited to certain days of the week only. Given the marginal difference in total travel time inclusive stop-over and the comfort offered by the airline, I booked my trip on Emirates with the usual short stop in Dubai. Otherwise, it would have been a stop-over in Chennai or Bangalore. </p><figure class="kg-card kg-gallery-card kg-width-wide kg-card-hascaption"><div class="kg-gallery-container"><div class="kg-gallery-row"><div class="kg-gallery-image"><img src="https://jochen.kirstaetter.name/content/images/2024/05/WP_20170406_09_58_15_Selfie.jpg" width="1918" height="1077" alt="C# Corner Annual Conference 2017" srcset="https://jochen.kirstaetter.name/content/images/size/w600/2024/05/WP_20170406_09_58_15_Selfie.jpg 600w, https://jochen.kirstaetter.name/content/images/size/w1000/2024/05/WP_20170406_09_58_15_Selfie.jpg 1000w, https://jochen.kirstaetter.name/content/images/size/w1600/2024/05/WP_20170406_09_58_15_Selfie.jpg 1600w, https://jochen.kirstaetter.name/content/images/2024/05/WP_20170406_09_58_15_Selfie.jpg 1918w" sizes="(min-width: 720px) 720px"></div><div class="kg-gallery-image"><img src="https://jochen.kirstaetter.name/content/images/2024/05/WP_20170406_11_11_38_Selfie.jpg" width="1918" height="1077" alt="C# Corner Annual Conference 2017" srcset="https://jochen.kirstaetter.name/content/images/size/w600/2024/05/WP_20170406_11_11_38_Selfie.jpg 600w, https://jochen.kirstaetter.name/content/images/size/w1000/2024/05/WP_20170406_11_11_38_Selfie.jpg 1000w, https://jochen.kirstaetter.name/content/images/size/w1600/2024/05/WP_20170406_11_11_38_Selfie.jpg 1600w, https://jochen.kirstaetter.name/content/images/2024/05/WP_20170406_11_11_38_Selfie.jpg 1918w" sizes="(min-width: 720px) 720px"></div></div></div><figcaption>Travelling with Emirates is quiet, comfortable and enjoyable</figcaption></figure><p>With the additional flexibility of multiple flights per day I opted for Emirates, again. And I even got a nice deal to upgrade to Business Class.</p><h2 id="first-impressions">First impressions</h2><p>After two unspectacular flights I arrived safely in Delhi during the afternoon. And thanks to the organised airport transfer it was a breeze to experience the traffic first-hand. Whew, I mean driving in Mauritius can be an adventure sometimes in certain areas but this topped everything. It is scary and fascinating at the same time, not sure whether I can describe it using words only. A three-lane road has five to six vehicles of any kind next to each other, ranging from bicycles to auto-rickshaw - aka tuk tuk) to busses and heavyload lorries. And everyone is honking.</p><p>Thankfully Manish is used to all of this and we arrived at the hotel in adequate time just to discover another novelty for me. The hotel, or more likely any hotel, seems to be a miniature fortress I got the impression. Heavy fencing around the property, armed units with machine guns slung over their shoulder, car inspection with mirrors to check for explosives, X-ray security scanners for your luggage, and metal detectors for people. Never seen this before...</p><p>Anyway, there was a heartwarming reception procedure while waiting for the check-in process to be completed. A bit exhausted I happily reached the hotel room to stretch out and relax a bit. My community fellow and room-mate Chervine arrived a day earlier.</p><figure class="kg-card kg-gallery-card kg-width-wide kg-card-hascaption"><div class="kg-gallery-container"><div class="kg-gallery-row"><div class="kg-gallery-image"><img src="https://jochen.kirstaetter.name/content/images/2024/05/WP_20170406_15_42_24_Pro.jpg" width="1261" height="791" alt="C# Corner Annual Conference 2017" srcset="https://jochen.kirstaetter.name/content/images/size/w600/2024/05/WP_20170406_15_42_24_Pro.jpg 600w, https://jochen.kirstaetter.name/content/images/size/w1000/2024/05/WP_20170406_15_42_24_Pro.jpg 1000w, https://jochen.kirstaetter.name/content/images/2024/05/WP_20170406_15_42_24_Pro.jpg 1261w" sizes="(min-width: 720px) 720px"></div><div class="kg-gallery-image"><img src="https://jochen.kirstaetter.name/content/images/2024/05/WP_20170406_17_20_52_Pro.jpg" width="1920" height="1080" alt="C# Corner Annual Conference 2017" srcset="https://jochen.kirstaetter.name/content/images/size/w600/2024/05/WP_20170406_17_20_52_Pro.jpg 600w, https://jochen.kirstaetter.name/content/images/size/w1000/2024/05/WP_20170406_17_20_52_Pro.jpg 1000w, https://jochen.kirstaetter.name/content/images/size/w1600/2024/05/WP_20170406_17_20_52_Pro.jpg 1600w, https://jochen.kirstaetter.name/content/images/2024/05/WP_20170406_17_20_52_Pro.jpg 1920w" sizes="(min-width: 720px) 720px"></div><div class="kg-gallery-image"><img src="https://jochen.kirstaetter.name/content/images/2024/05/WP_20170406_17_20_56_Pro.jpg" width="1920" height="1080" alt="C# Corner Annual Conference 2017" srcset="https://jochen.kirstaetter.name/content/images/size/w600/2024/05/WP_20170406_17_20_56_Pro.jpg 600w, https://jochen.kirstaetter.name/content/images/size/w1000/2024/05/WP_20170406_17_20_56_Pro.jpg 1000w, https://jochen.kirstaetter.name/content/images/size/w1600/2024/05/WP_20170406_17_20_56_Pro.jpg 1600w, https://jochen.kirstaetter.name/content/images/2024/05/WP_20170406_17_20_56_Pro.jpg 1920w" sizes="(min-width: 720px) 720px"></div></div><div class="kg-gallery-row"><div class="kg-gallery-image"><img src="https://jochen.kirstaetter.name/content/images/2024/05/WP_20170406_21_56_57_Pro.jpg" width="1861" height="1047" alt="C# Corner Annual Conference 2017" srcset="https://jochen.kirstaetter.name/content/images/size/w600/2024/05/WP_20170406_21_56_57_Pro.jpg 600w, https://jochen.kirstaetter.name/content/images/size/w1000/2024/05/WP_20170406_21_56_57_Pro.jpg 1000w, https://jochen.kirstaetter.name/content/images/size/w1600/2024/05/WP_20170406_21_56_57_Pro.jpg 1600w, https://jochen.kirstaetter.name/content/images/2024/05/WP_20170406_21_56_57_Pro.jpg 1861w" sizes="(min-width: 720px) 720px"></div><div class="kg-gallery-image"><img src="https://jochen.kirstaetter.name/content/images/2024/05/WP_20170406_23_02_08_Pro-1.jpg" width="1652" height="1724" alt="C# Corner Annual Conference 2017" srcset="https://jochen.kirstaetter.name/content/images/size/w600/2024/05/WP_20170406_23_02_08_Pro-1.jpg 600w, https://jochen.kirstaetter.name/content/images/size/w1000/2024/05/WP_20170406_23_02_08_Pro-1.jpg 1000w, https://jochen.kirstaetter.name/content/images/size/w1600/2024/05/WP_20170406_23_02_08_Pro-1.jpg 1600w, https://jochen.kirstaetter.name/content/images/2024/05/WP_20170406_23_02_08_Pro-1.jpg 1652w" sizes="(min-width: 720px) 720px"></div></div><div class="kg-gallery-row"><div class="kg-gallery-image"><img src="https://jochen.kirstaetter.name/content/images/2024/05/WP_20170406_20_32_40_Pro.jpg" width="1920" height="1080" alt="C# Corner Annual Conference 2017" srcset="https://jochen.kirstaetter.name/content/images/size/w600/2024/05/WP_20170406_20_32_40_Pro.jpg 600w, https://jochen.kirstaetter.name/content/images/size/w1000/2024/05/WP_20170406_20_32_40_Pro.jpg 1000w, https://jochen.kirstaetter.name/content/images/size/w1600/2024/05/WP_20170406_20_32_40_Pro.jpg 1600w, https://jochen.kirstaetter.name/content/images/2024/05/WP_20170406_20_32_40_Pro.jpg 1920w" sizes="(min-width: 720px) 720px"></div><div class="kg-gallery-image"><img src="https://jochen.kirstaetter.name/content/images/2024/05/WP_20170406_21_09_33_Pro.jpg" width="1503" height="1020" alt="C# Corner Annual Conference 2017" srcset="https://jochen.kirstaetter.name/content/images/size/w600/2024/05/WP_20170406_21_09_33_Pro.jpg 600w, https://jochen.kirstaetter.name/content/images/size/w1000/2024/05/WP_20170406_21_09_33_Pro.jpg 1000w, https://jochen.kirstaetter.name/content/images/2024/05/WP_20170406_21_09_33_Pro.jpg 1503w" sizes="(min-width: 720px) 720px"></div></div></div><figcaption>Arriving in Dehli, India</figcaption></figure><p>Later this evening, we met with <a href="https://twitter.com/debug_mode">Dhananjay (DJ) Kumar</a> and we talked a bit about Mauritius, India, developer communities in general, and all kind of other interesting topics. Totally unexpected and surprising, DJ gifted me the book "The power of habit" by Charles Duhigg. Very much appreciated.</p><p>After a wonderful speakers dinner organised by C# Corner it was time to call it a day as there had been plans made for us the next day. This meant to catch some Zzzz's and then wake up earlier than usual.</p><h2 id="road-trip-to-mathura">Road trip to Mathura</h2><p>Guess what? It's Uber time! First time, riding on an Uber... It was booked by our hosts in order to meet other speakers for today's trip to Mathura. Speaking in front of CS students at one of the local universities. Initially the Uber trip started quite good, the driver came to the hotel in time and we were off for a quick 30 minutes drive to join the others. And then <strong>he fell asleep</strong> on the wheel...</p><p>After the second time grazing the wall in the middle of the highway, the traffic separation, we all urged the driver to stop the car instantly and we hauled another Uber to continue the trip safely. With quite some delay we met with a fellow from C# Corner and we were finally off to Mathura.</p><p>Interestingly, the <a href="https://en.wikipedia.org/wiki/Yamuna_Expressway">Yamuna Expressway</a> passes along the <a href="https://en.wikipedia.org/wiki/Buddh_International_Circuit">Buddh International Circuit</a> where the Indian Grand Prix in Formula One used to be. A track dominated by Sebastian Vettel during its short period on the F1 calendar. For the final stretch from the expressway to Mathura we drove on <u><em>regular roads</em></u>. We even had to take a diversion through the fields to reach the GLA University in Mathura.</p><p>Joining the other speakers and checking out the agenda of the day there was little perparations for my talk on "Advantages and Opportunities of Cross-Platform Development". During my session I explained to the students present the different options and tools available to dive into cross-platform development. Afterwards, there had been quite a number of questions regarding Cordova, Xamarin and Electron which I gladly answered to my best knowledge. I wasn't aware about certain customs, the whole at the university we have been treated with utterly importance. I felt as some kind of celebrity; just showing up and taking the stage to talk. Positive although unusual impressions.</p><figure class="kg-card kg-gallery-card kg-width-wide kg-card-hascaption"><div class="kg-gallery-container"><div class="kg-gallery-row"><div class="kg-gallery-image"><img src="https://jochen.kirstaetter.name/content/images/2024/05/WP_20170407_10_30_46_Pro.jpg" width="1631" height="917" alt="C# Corner Annual Conference 2017" srcset="https://jochen.kirstaetter.name/content/images/size/w600/2024/05/WP_20170407_10_30_46_Pro.jpg 600w, https://jochen.kirstaetter.name/content/images/size/w1000/2024/05/WP_20170407_10_30_46_Pro.jpg 1000w, https://jochen.kirstaetter.name/content/images/size/w1600/2024/05/WP_20170407_10_30_46_Pro.jpg 1600w, https://jochen.kirstaetter.name/content/images/2024/05/WP_20170407_10_30_46_Pro.jpg 1631w" sizes="(min-width: 720px) 720px"></div><div class="kg-gallery-image"><img src="https://jochen.kirstaetter.name/content/images/2024/05/WP_20170407_10_48_51_Pro.jpg" width="1418" height="734" alt="C# Corner Annual Conference 2017" srcset="https://jochen.kirstaetter.name/content/images/size/w600/2024/05/WP_20170407_10_48_51_Pro.jpg 600w, https://jochen.kirstaetter.name/content/images/size/w1000/2024/05/WP_20170407_10_48_51_Pro.jpg 1000w, https://jochen.kirstaetter.name/content/images/2024/05/WP_20170407_10_48_51_Pro.jpg 1418w" sizes="(min-width: 720px) 720px"></div></div><div class="kg-gallery-row"><div class="kg-gallery-image"><img src="https://jochen.kirstaetter.name/content/images/2024/05/WP_20170407_18_38_19_Pro-1.jpg" width="1641" height="678" alt="C# Corner Annual Conference 2017" srcset="https://jochen.kirstaetter.name/content/images/size/w600/2024/05/WP_20170407_18_38_19_Pro-1.jpg 600w, https://jochen.kirstaetter.name/content/images/size/w1000/2024/05/WP_20170407_18_38_19_Pro-1.jpg 1000w, https://jochen.kirstaetter.name/content/images/size/w1600/2024/05/WP_20170407_18_38_19_Pro-1.jpg 1600w, https://jochen.kirstaetter.name/content/images/2024/05/WP_20170407_18_38_19_Pro-1.jpg 1641w" sizes="(min-width: 720px) 720px"></div><div class="kg-gallery-image"><img src="https://jochen.kirstaetter.name/content/images/2024/05/WP_20170407_22_03_26_Pro.jpg" width="1741" height="836" alt="C# Corner Annual Conference 2017" srcset="https://jochen.kirstaetter.name/content/images/size/w600/2024/05/WP_20170407_22_03_26_Pro.jpg 600w, https://jochen.kirstaetter.name/content/images/size/w1000/2024/05/WP_20170407_22_03_26_Pro.jpg 1000w, https://jochen.kirstaetter.name/content/images/size/w1600/2024/05/WP_20170407_22_03_26_Pro.jpg 1600w, https://jochen.kirstaetter.name/content/images/2024/05/WP_20170407_22_03_26_Pro.jpg 1741w" sizes="(min-width: 720px) 720px"></div></div></div><figcaption>Day trip to the Confrencia at GLA University in Mathura</figcaption></figure><p>The trip back to Delhi got us into a bit of rush hour. I mean, it's not like there's no traffic all day long but around early evening it seems to intensify by a magnitude or two. Mind-boggling driving experience! Compared to that, driving in Mauritius is like secured road education for young learners at kindergarten. And I figured that the constant honking is just a way to say 'Hello, I'm doing great and I'm an active participant on the road'. Nothing special about that.</p><p>We rounded up the day with a speakers dinner back at the hotel. Some of the seasoned speakers shared their experience on delivering a great talk and offered their valuable advice to others. Again, it was a very pleasant activity and well received.</p><h2 id="the-conference">The conference</h2><p>Despite my session being scheduled during the early afternoon, I woke up quite early to seize the opportunity to explore the conference venue. There were multiple rooms for the tracks and a large exhibition area for vendors and partners of the event. Big style stuff and very much like any of the European conferences I attended in the past. The registration desks were already buzzing with people. Everyone being really excited about the big day.</p><p>As mentioned, there were multiple tracks in parallel and my session had been assigned to Track 1 which was occupying the main hall with the largest amount of seats. Whew, no pressure ;-)</p><p>Throughout the day it became appeared that we experienced an increasing delay regarding the starting times of the sessions. Well, nothing to worry about in India, and I have to admit that I was glad for some extra time to prepare myself for the talk. Quick hardware check and also verifying that all code samples and demos were working as expected and I was ready to rumble. It didn't go as smoothly as I hoped for but I had some source code to show on how to develop .NET Core applications on Linux. Back in the days I used Visual Studio Code and the `dotnet` CLI to convey the message to the audience.</p><figure class="kg-card kg-gallery-card kg-width-wide kg-card-hascaption"><div class="kg-gallery-container"><div class="kg-gallery-row"><div class="kg-gallery-image"><img src="https://jochen.kirstaetter.name/content/images/2024/08/WP_20170408_18_24_07_Pro.jpg" width="1080" height="1920" alt="C# Corner Annual Conference 2017" srcset="https://jochen.kirstaetter.name/content/images/size/w600/2024/08/WP_20170408_18_24_07_Pro.jpg 600w, https://jochen.kirstaetter.name/content/images/size/w1000/2024/08/WP_20170408_18_24_07_Pro.jpg 1000w, https://jochen.kirstaetter.name/content/images/2024/08/WP_20170408_18_24_07_Pro.jpg 1080w" sizes="(min-width: 720px) 720px"></div><div class="kg-gallery-image"><img src="https://jochen.kirstaetter.name/content/images/2024/08/WP_20170408_07_26_32_Selfie-1--1.jpg" width="1919" height="1080" alt="C# Corner Annual Conference 2017" srcset="https://jochen.kirstaetter.name/content/images/size/w600/2024/08/WP_20170408_07_26_32_Selfie-1--1.jpg 600w, https://jochen.kirstaetter.name/content/images/size/w1000/2024/08/WP_20170408_07_26_32_Selfie-1--1.jpg 1000w, https://jochen.kirstaetter.name/content/images/size/w1600/2024/08/WP_20170408_07_26_32_Selfie-1--1.jpg 1600w, https://jochen.kirstaetter.name/content/images/2024/08/WP_20170408_07_26_32_Selfie-1--1.jpg 1919w" sizes="(min-width: 720px) 720px"></div></div><div class="kg-gallery-row"><div class="kg-gallery-image"><img src="https://jochen.kirstaetter.name/content/images/2024/08/WP_20170408_18_51_45_Pro.jpg" width="1825" height="837" alt="C# Corner Annual Conference 2017" srcset="https://jochen.kirstaetter.name/content/images/size/w600/2024/08/WP_20170408_18_51_45_Pro.jpg 600w, https://jochen.kirstaetter.name/content/images/size/w1000/2024/08/WP_20170408_18_51_45_Pro.jpg 1000w, https://jochen.kirstaetter.name/content/images/size/w1600/2024/08/WP_20170408_18_51_45_Pro.jpg 1600w, https://jochen.kirstaetter.name/content/images/2024/08/WP_20170408_18_51_45_Pro.jpg 1825w" sizes="(min-width: 720px) 720px"></div><div class="kg-gallery-image"><img src="https://jochen.kirstaetter.name/content/images/2024/08/WP_20170408_16_04_30_Pro.jpg" width="972" height="1296" alt="C# Corner Annual Conference 2017" srcset="https://jochen.kirstaetter.name/content/images/size/w600/2024/08/WP_20170408_16_04_30_Pro.jpg 600w, https://jochen.kirstaetter.name/content/images/2024/08/WP_20170408_16_04_30_Pro.jpg 972w" sizes="(min-width: 720px) 720px"></div></div></div><figcaption>Speaking in the main track of C# Corner Conference 2017</figcaption></figure><p>Afterwards, I had some great conversation with Joseph Guadagno about the Microsoft MVP program in general, and we cross-checked our list of MVP contacts. It was pretty amusing to exchange stories regarding some of the folks we both know. Later on, I chit-chatted a bit with <a href="https://se.linkedin.com/in/noopman">Magnus Mårtensson</a>, <a href="https://www.linkedin.com/in/davidmccarter">David McCarter</a>, <a href="https://in.linkedin.com/in/pinaldave">Pinal Dave</a>, and a couple more speakers about their activities related to .NET, SQL Server and of course the C# Corner community. The had been numerous nuggets of great advice for growing our community in Mauritius and I got some ideas for the annual Developers Conference in Mauritius, too.</p><p>Later that evening, all speakers and helpers of the conference were invited for a treat: Speakers dinner at a rooftop club in one of the suburbs of Delhi. Great fun I can tell you. And very interesting conversations, lots of jokes and laughter, and finally some great snacks to enjoy. Dunno when but it must have been after midnight that I dropped dead into my bed.</p><h2 id="agra">Agra</h2><p>A day to relax and go sight-seeing. Chervine came up with the idea of visiting places. First and foremost, the Taj Mahal.</p><figure class="kg-card kg-image-card kg-width-wide"><img src="https://jochen.kirstaetter.name/content/images/2024/06/WP_20170409_15_17_47_Pro-1.jpg" class="kg-image" alt="C# Corner Annual Conference 2017" srcset="https://jochen.kirstaetter.name/content/images/size/w600/2024/06/WP_20170409_15_17_47_Pro-1.jpg 600w, https://jochen.kirstaetter.name/content/images/size/w1000/2024/06/WP_20170409_15_17_47_Pro-1.jpg 1000w, https://jochen.kirstaetter.name/content/images/2024/06/WP_20170409_15_17_47_Pro-1.jpg 1280w" sizes="(min-width: 1200px) 1200px"></figure><figure class="kg-card kg-gallery-card kg-width-wide"><div class="kg-gallery-container"><div class="kg-gallery-row"><div class="kg-gallery-image"><img src="https://jochen.kirstaetter.name/content/images/2024/06/WP_20170409_14_37_09_Pro.jpg" width="1280" height="853" alt="C# Corner Annual Conference 2017" srcset="https://jochen.kirstaetter.name/content/images/size/w600/2024/06/WP_20170409_14_37_09_Pro.jpg 600w, https://jochen.kirstaetter.name/content/images/size/w1000/2024/06/WP_20170409_14_37_09_Pro.jpg 1000w, https://jochen.kirstaetter.name/content/images/2024/06/WP_20170409_14_37_09_Pro.jpg 1280w" sizes="(min-width: 720px) 720px"></div><div class="kg-gallery-image"><img src="https://jochen.kirstaetter.name/content/images/2024/06/WP_20170409_15_08_58_Pro.jpg" width="1280" height="720" alt="C# Corner Annual Conference 2017" srcset="https://jochen.kirstaetter.name/content/images/size/w600/2024/06/WP_20170409_15_08_58_Pro.jpg 600w, https://jochen.kirstaetter.name/content/images/size/w1000/2024/06/WP_20170409_15_08_58_Pro.jpg 1000w, https://jochen.kirstaetter.name/content/images/2024/06/WP_20170409_15_08_58_Pro.jpg 1280w" sizes="(min-width: 720px) 720px"></div><div class="kg-gallery-image"><img src="https://jochen.kirstaetter.name/content/images/2024/06/WP_20170409_15_43_03_Selfie.jpg" width="1280" height="816" alt="C# Corner Annual Conference 2017" srcset="https://jochen.kirstaetter.name/content/images/size/w600/2024/06/WP_20170409_15_43_03_Selfie.jpg 600w, https://jochen.kirstaetter.name/content/images/size/w1000/2024/06/WP_20170409_15_43_03_Selfie.jpg 1000w, https://jochen.kirstaetter.name/content/images/2024/06/WP_20170409_15_43_03_Selfie.jpg 1280w" sizes="(min-width: 720px) 720px"></div></div><div class="kg-gallery-row"><div class="kg-gallery-image"><img src="https://jochen.kirstaetter.name/content/images/2024/06/WP_20170409_16_26_01_Pro.jpg" width="1920" height="1080" alt="C# Corner Annual Conference 2017" srcset="https://jochen.kirstaetter.name/content/images/size/w600/2024/06/WP_20170409_16_26_01_Pro.jpg 600w, https://jochen.kirstaetter.name/content/images/size/w1000/2024/06/WP_20170409_16_26_01_Pro.jpg 1000w, https://jochen.kirstaetter.name/content/images/size/w1600/2024/06/WP_20170409_16_26_01_Pro.jpg 1600w, https://jochen.kirstaetter.name/content/images/2024/06/WP_20170409_16_26_01_Pro.jpg 1920w" sizes="(min-width: 720px) 720px"></div><div class="kg-gallery-image"><img src="https://jochen.kirstaetter.name/content/images/2024/06/WP_20170409_16_16_43_Pro.jpg" width="1280" height="719" alt="C# Corner Annual Conference 2017" srcset="https://jochen.kirstaetter.name/content/images/size/w600/2024/06/WP_20170409_16_16_43_Pro.jpg 600w, https://jochen.kirstaetter.name/content/images/size/w1000/2024/06/WP_20170409_16_16_43_Pro.jpg 1000w, https://jochen.kirstaetter.name/content/images/2024/06/WP_20170409_16_16_43_Pro.jpg 1280w" sizes="(min-width: 720px) 720px"></div><div class="kg-gallery-image"><img src="https://jochen.kirstaetter.name/content/images/2024/06/WP_20170409_15_50_37_Pro.jpg" width="1920" height="1080" alt="C# Corner Annual Conference 2017" srcset="https://jochen.kirstaetter.name/content/images/size/w600/2024/06/WP_20170409_15_50_37_Pro.jpg 600w, https://jochen.kirstaetter.name/content/images/size/w1000/2024/06/WP_20170409_15_50_37_Pro.jpg 1000w, https://jochen.kirstaetter.name/content/images/size/w1600/2024/06/WP_20170409_15_50_37_Pro.jpg 1600w, https://jochen.kirstaetter.name/content/images/2024/06/WP_20170409_15_50_37_Pro.jpg 1920w" sizes="(min-width: 720px) 720px"></div></div><div class="kg-gallery-row"><div class="kg-gallery-image"><img src="https://jochen.kirstaetter.name/content/images/2024/06/WP_20170409_16_33_12_Pro.jpg" width="1280" height="670" alt="C# Corner Annual Conference 2017" srcset="https://jochen.kirstaetter.name/content/images/size/w600/2024/06/WP_20170409_16_33_12_Pro.jpg 600w, https://jochen.kirstaetter.name/content/images/size/w1000/2024/06/WP_20170409_16_33_12_Pro.jpg 1000w, https://jochen.kirstaetter.name/content/images/2024/06/WP_20170409_16_33_12_Pro.jpg 1280w" sizes="(min-width: 720px) 720px"></div><div class="kg-gallery-image"><img src="https://jochen.kirstaetter.name/content/images/2024/06/WP_20170409_15_54_10_Pro.jpg" width="686" height="1280" alt="C# Corner Annual Conference 2017" srcset="https://jochen.kirstaetter.name/content/images/size/w600/2024/06/WP_20170409_15_54_10_Pro.jpg 600w, https://jochen.kirstaetter.name/content/images/2024/06/WP_20170409_15_54_10_Pro.jpg 686w"></div></div></div></figure><h2 id="exploring-delhi">Exploring Delhi</h2><p>Last day in India for this trip and my flight is early in the evening. Hence, we decided to explore the city of Delhi. After a savvy breakfast Chervine and I were </p><figure class="kg-card kg-image-card kg-width-full"><img src="https://jochen.kirstaetter.name/content/images/2024/06/WP_20170410_18_01_08_Panorama.jpg" class="kg-image" alt="C# Corner Annual Conference 2017" srcset="https://jochen.kirstaetter.name/content/images/size/w600/2024/06/WP_20170410_18_01_08_Panorama.jpg 600w, https://jochen.kirstaetter.name/content/images/size/w1000/2024/06/WP_20170410_18_01_08_Panorama.jpg 1000w, https://jochen.kirstaetter.name/content/images/size/w1600/2024/06/WP_20170410_18_01_08_Panorama.jpg 1600w, https://jochen.kirstaetter.name/content/images/2024/06/WP_20170410_18_01_08_Panorama.jpg 1911w"></figure><h2 id="personal-thoughts">Personal thoughts</h2><p>It's quite difficult to express my experience and impressions of India, in particular due to the very short stay, into the right words. Let me say it like this: </p><p>It's overwhelming - in any sense and direction!</p><p>The first thing that hit me was the incredible amount of people nearly everywhere. Then there is the adventure of road traffic. Frankly, I wouldn't dare to drive around Delhi myself. Not because I don't know how to drive but probably regarding the level of interactions, the level of concentration, and the uncommon levels of sound (honk honk). It's too crowded, perhaps chaotic at certain stages but that's the beauty of it I would say.</p><p>Those few days in the state of Uttar Pradesh (UP) were really amazing and I had a great time mingling with other speakers and attendees of the C# Corner Annual Conference. The trips to Mathura and Agra gave me a small glimpse of the beauty of this humongous country called India. Walking through one of the many markets in Delhi and exploring the small shops surrounding it was mesmerising. Seeing the India Gate, the triumphal arch in Delhi, as well as Rashtrapati Bhavan with large park area was a nice treat at the end of my visit.</p><p>I'm hoping that this isn't my last trip to India. There are surely other cities like Darjeeling, Chennai, Bangalore, Mumbai, etc. worth a visit. Let's see what the future holds.</p><p>My thanks and gratitude to the community fellows at C# Corner. Keep shining!</p>]]></content:encoded></item><item><title><![CDATA[Untrack files in .gitignore]]></title><description><![CDATA[Despite best effort and preparation of your precious source code one day you might be facing the situation that there is one or more files in your development workspace that doesn't belong into your git repository.]]></description><link>https://jochen.kirstaetter.name/untrack-files-in-gitignore/</link><guid isPermaLink="false">65e74ff0f2f01b106a425032</guid><category><![CDATA[Development]]></category><dc:creator><![CDATA[Jochen Kirstätter]]></dc:creator><pubDate>Fri, 05 Apr 2024 12:22:27 GMT</pubDate><media:content url="https://jochen.kirstaetter.name/content/images/2024/04/Gemini_Generated_Image_pxek4spxek4spxek.jpeg" medium="image"/><content:encoded><![CDATA[<img src="https://jochen.kirstaetter.name/content/images/2024/04/Gemini_Generated_Image_pxek4spxek4spxek.jpeg" alt="Untrack files in .gitignore"><p>Despite best effort and preparation of your precious source code one day you might be facing the situation that there is one or more files in your development workspace that doesn't belong into your git repository.</p><p>In general, that's a scenario to use the <code>.gitignore</code> file and exclude such file(s) from being considered or tracked for your repository. This works great but requires that you cover all your tracks regarding potential files, file extensions or folders you don't want to set under version control. Predicting the future is hard.</p><p>Plus, changes and audits happen. Meaning, a previously added file should be ignored from now on. Excluding such file in <code>.gitignore</code> won't work as expected out of the box. Such a file needs to be <em>untracked </em>first, and then excluded.</p><h2 id="behold-a-single-one">Behold a single one</h2><p>To untrack a <em><em>single</em></em> file that has already been added/initialized to your repository, <em><em>i.e.</em></em>, stop tracking the file but not delete it from your system use: </p><pre><code>git rm --cached filename</code></pre><p>To undo the previous command, add that single file back using <code>git add filename</code>.</p><h2 id="hold-my-beer-">Hold my beer!</h2><p>Occasionally, there is more than a single file to handle. Here's how to untrack <em><em>every</em></em> file that is now in your <code>.gitignore</code> and then add all other files back.</p><p><strong><strong>First commit any outstanding code changes</strong>!</strong></p><p>Then, run this command to untrack everything.</p><pre><code>git rm -r --cached .
</code></pre><p>This removes any changed files from the <em><em>index</em> </em>(staging area).</p><p>Afterwards, add everything back into the <em>index</em>, now respecting <code>.gitignore</code> excluding certain files and folders.</p><pre><code>git add .
</code></pre><p>Note: Make sure to commit all your important changes before running <code>git add .</code> Otherwise, you will lose any changes to other files.</p><p>Complete the changes by commit.</p><pre><code>git commit -m ".gitignore is now working"
</code></pre><h2 id="note-of-caution">Note of caution</h2><p>Please be careful, when you push this to a repository and pull from somewhere else into a state where those files are still tracked, those files will be <strong>deleted</strong>.</p><!--kg-card-begin: html--><small>Image credit: Gemini using prompt <i>create an image showing a junction of railroad tracks</i></small><!--kg-card-end: html-->]]></content:encoded></item><item><title><![CDATA[Quickstart: Use Gemini with .NET (Vertex AI)]]></title><description><![CDATA[Use Gemini in .NET in shortest time following this quickstart to configure Vertex AI on Google Cloud and add generative AI features to your apps.]]></description><link>https://jochen.kirstaetter.name/quickstart-using-gemini-with-net-vertex-ai/</link><guid isPermaLink="false">660c3390f2f01b106a42522e</guid><category><![CDATA[Development]]></category><dc:creator><![CDATA[Jochen Kirstätter]]></dc:creator><pubDate>Wed, 03 Apr 2024 09:31:20 GMT</pubDate><media:content url="https://jochen.kirstaetter.name/content/images/2024/04/Gemini_Generated_Image.jpeg" medium="image"/><content:encoded><![CDATA[<img src="https://jochen.kirstaetter.name/content/images/2024/04/Gemini_Generated_Image.jpeg" alt="Quickstart: Use Gemini with .NET (Vertex AI)"><p>This quickstart shows you how to get started with the Gemini API in Vertex AI on Google Cloud using an SDK for .NET called <a href="https://www.nuget.org/packages/Mscc.GenerativeAI/">Mscc.GenerativeAI</a>.</p><h2 id="prerequisites">Prerequisites</h2><p>To complete this quickstart locally, ensure that your .NET development meets the following requirements:</p><ul><li>.NET 6+ or </li><li>.NET Framework 4.7.2+</li><li>Account on Google Cloud</li></ul><p>The NuGet package also supports .NET Standard 2.0.</p><h2 id="get-set-up-on-google-cloud">Get set up on Google Cloud</h2><p>To get you started using Vertex AI, follow the <a href="https://cloud.google.com/vertex-ai/docs/start/cloud-environment">instructions in the official guide</a>. You need to complete the following steps:</p><ul><li>Set up a project</li><li>Enable billing for the Google Cloud project</li><li>Enable Vertex AI APIs</li><li>Install the Google Cloud CLI</li><li><a href="https://cloud.google.com/docs/authentication/provide-credentials-adc">Set up Application Default Credentials</a> (ADC)</li></ul><p>In conclusion, you need the project ID associated with your project, and choose a <a href="https://cloud.google.com/vertex-ai/generative-ai/docs/learn/locations">supported region</a>.</p><p>In order to keep private, sensitive information and secrets out of your source code repositories, it is recommended to use either Environment Variables, User Secrets, or a Key/Secrets Manager to retrieve data like an API key. </p><p>Here, I'm going to create an <code>.env</code> file and place it into the project folder with the following content.</p><pre><code>GOOGLE_PROJECT_ID=&lt;your project ID&gt;
GOOGLE_REGION=us-central1</code></pre><p>To access the value of a variable that is defined in a <code>.env</code> file, use <code>$dotenv</code>. More details are described under <a href="https://learn.microsoft.com/en-us/aspnet/core/test/http-files?view=aspnetcore-8.0#environment-variables">Environment Variables</a>  in the official documentation.</p><p>Set the file properties with a Build action of <code>None</code> and copy instructions of <code>Copy, if newer</code>.</p><pre><code>&lt;None Update=".env" Condition="Exists('.env')"&gt;
    &lt;CopyToOutputDirectory&gt;PreserveNewest&lt;/CopyToOutputDirectory&gt;
&lt;/None&gt;</code></pre><h2 id="install-the-sdk-nuget-package">Install the SDK / NuGet package</h2><p>The SDK for .NET for the Gemini API is contained in the <code>Mscc.GenerativeAI</code> package. Install the dependency using dotnet CLI:</p><pre><code>dotnet add package Mscc.GenerativeAI</code></pre><p>See <a href="https://www.nuget.org/packages/Mscc.GenerativeAI/">README</a> for alternative options, like the NuGet Package Manager.</p><p><strong>Note:</strong> <em>This is a quickstart to Gemini on Vertex AI. If you need additional authentication options see <a href="https://www.nuget.org/packages/Mscc.GenerativeAI/">README</a> of Mscc.GenerativeAI and consider to add the package reference <a href="https://www.nuget.org/packages/Mscc.GenerativeAI.Google/">Mscc.GenerativeAI.Google</a> which is based on the <a href="https://cloud.google.com/dotnet/docs/reference">.NET Cloud Client Libraries</a>.</em></p><h2 id="initialize-the-generative-model">Initialize the Generative Model</h2><p>Before you can make any API calls, you need to add a reference to the namespace <code>Mscc.GenerativeAI</code> and initialize the Generative Model.</p><pre><code>using Mscc.GenerativeAI;

var vertexAI = new VertexAI(
    projectId: Environment.GetEnvironmentVariable("GOOGLE_PROJECT_ID"), 
    region: Environment.GetEnvironmentVariable("GOOGLE_REGION"));
var model = vertexAI.GenerativeModel(model: Model.Gemini10Pro);</code></pre><p>The necessary access token to authenticate against Google Cloud is retrieved from the Application Default Credentials or the Google Client Library, in case that you are using the Mscc.GenerativeAI.Google package.</p><h2 id="generate-text">Generate Text</h2><pre><code>var prompt = "Write a poem about Japanese koi.";
var responseStream = model.GenerateContentStream(prompt);

// Use StringBuilder to append the streamed responses
await foreach (var response in responseStream)
{
    var response = await model.GenerateContent();
    // optional, check for response.Candidates[0].FinishReason
    Console.WriteLine(response.Text);
}</code></pre><p><strong>Note:</strong> <em>The package Mscc.GenerativeAI offers a unified developer experience across Google AI and Vertex AI provided by the interface IGenerativeAI. Meaning, the non-streaming method</em> `GenerateContent` <em>is available in Vertex AI and works as expected. </em></p><h2 id="what-s-next">What's next</h2><p>Explore the <a href="https://www.nuget.org/packages/Mscc.GenerativeAI/">README</a> of the NuGet package which has more samples documented. All unit tests are accessible in the <a href="https://github.com/mscraftsman/generative-ai">GitHub repository</a>:</p><figure class="kg-card kg-bookmark-card"><a class="kg-bookmark-container" href="https://github.com/mscraftsman/generative-ai"><div class="kg-bookmark-content"><div class="kg-bookmark-title">GitHub - mscraftsman/generative-ai: Gemini AI Client for .NET</div><div class="kg-bookmark-description">Gemini AI Client for .NET. Contribute to mscraftsman/generative-ai development by creating an account on GitHub.</div><div class="kg-bookmark-metadata"><img class="kg-bookmark-icon" src="https://github.githubassets.com/favicons/favicon.svg" alt="Quickstart: Use Gemini with .NET (Vertex AI)"><span class="kg-bookmark-author">GitHub</span><span class="kg-bookmark-publisher">mscraftsman</span></div></div><div class="kg-bookmark-thumbnail"><img src="https://opengraph.githubassets.com/75de26a26c206cf142204c77b13e5c9bcf75e72f9558f35bc27484c20585a4fe/mscraftsman/generative-ai" alt="Quickstart: Use Gemini with .NET (Vertex AI)"></div></a></figure><p>If you're new to generative AI models, you might want to look at the <a href="https://ai.google.dev/docs/concepts">concepts guide</a> and the <a href="https://ai.google.dev/docs/gemini_api_overview">Gemini API overview</a> before trying a quickstart.</p><h2 id="what-s-the-difference-from-google-ai-gemini-api">What's the difference from Google AI Gemini API</h2><p>The Vertex AI Gemini API and Google AI Gemini API both let you incorporate the capabilities of Gemini models into your applications. The platform that's right for you depends on your goals.</p><p>The Vertex AI Gemini API is designed for developers and enterprises for use in scaled deployments. It offers features such as enterprise security, data residency, performance, and technical support. If you're an existing Google Cloud customer or deploy medium to large scale applications, you're in the right place.</p><p>If you're a hobbyist, student, or developer who is new to Google Cloud, try the <a href="https://jochen.kirstaetter.name/quickstart-use-gemini-with-net/">Google AI Gemini API</a>, which is suitable for experimentation, prototyping, and small deployments. If you're looking for a way to use Gemini directly from your mobile and web apps, see the Google AI SDKs for Android, Swift, and web.</p><!--kg-card-begin: html--><small>Image credit: Gemini using prompt <em>Create an image showing the fast start of a race in motor sport.</em></small><!--kg-card-end: html-->]]></content:encoded></item><item><title><![CDATA[Quickstart: Use Gemini with .NET (Google AI)]]></title><description><![CDATA[Less than five minutes to get started with Google Gemini API in .NET using the Mscc.GenerativeAI package. It's like a few lines of code only to empower your app with generative AI powered by Google Gemini.]]></description><link>https://jochen.kirstaetter.name/quickstart-use-gemini-with-net/</link><guid isPermaLink="false">660853eef2f01b106a425038</guid><category><![CDATA[Development]]></category><dc:creator><![CDATA[Jochen Kirstätter]]></dc:creator><pubDate>Tue, 02 Apr 2024 12:54:43 GMT</pubDate><media:content url="https://jochen.kirstaetter.name/content/images/2024/04/Gemini_Generated_Image-4-.jpeg" medium="image"/><content:encoded><![CDATA[<img src="https://jochen.kirstaetter.name/content/images/2024/04/Gemini_Generated_Image-4-.jpeg" alt="Quickstart: Use Gemini with .NET (Google AI)"><p>This quickstart shows you how to get started with the Gemini API using an SDK for .NET called <a href="https://www.nuget.org/packages/Mscc.GenerativeAI/">Mscc.GenerativeAI</a>.</p><h2 id="prerequisites">Prerequisites</h2><p>To complete this quickstart locally, ensure that your .NET development meets the following requirements:</p><ul><li>.NET 6+ or </li><li>.NET Framework 4.7.2+</li></ul><p>The NuGet package also supports .NET Standard 2.0.</p><h2 id="set-up-your-api-key">Set up your API key</h2><p>To use the Gemini API, you'll need an API key. If you don't already have one, create a key in <a href="https://aistudio.google.com/app/apikey">Google AI Studio</a>.</p><!--kg-card-begin: html--><a class="button button-primary" href="https://aistudio.google.com/app/apikey" target="_blank" rel="noopener noreferrer">Get an API key</a>
<!--kg-card-end: html--><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://jochen.kirstaetter.name/content/images/2024/02/Screenshot-from-2024-02-22-13-47-53.png" class="kg-image" alt="Quickstart: Use Gemini with .NET (Google AI)" srcset="https://jochen.kirstaetter.name/content/images/size/w600/2024/02/Screenshot-from-2024-02-22-13-47-53.png 600w, https://jochen.kirstaetter.name/content/images/2024/02/Screenshot-from-2024-02-22-13-47-53.png 769w" sizes="(min-width: 720px) 720px"><figcaption>Create an API key to access Gemini REST API</figcaption></figure><p>In order to keep private, sensitive information and secrets out of your source code repositories, it is recommended to use either Environment Variables, User Secrets, or a Key/Secrets Manager to retrieve data like an API key. Here, I'm going to create an <code>.env</code> file and place it into the project folder with the following content.</p><pre><code>GOOGLE_API_KEY=&lt;The generated Gemini API key&gt;</code></pre><p>To access the value of a variable that is defined in a <code>.env</code> file, use <code>$dotenv</code>. More details are described under <a href="https://learn.microsoft.com/en-us/aspnet/core/test/http-files?view=aspnetcore-8.0#environment-variables">Environment Variables</a>  in the official documentation.</p><p>Set the file properties with a Build action of <code>None</code> and copy instructions of <code>Copy, if newer</code>.</p><pre><code>&lt;None Update=".env" Condition="Exists('.env')"&gt;
    &lt;CopyToOutputDirectory&gt;PreserveNewest&lt;/CopyToOutputDirectory&gt;
&lt;/None&gt;</code></pre><h2 id="install-the-sdk-nuget-package">Install the SDK / NuGet package</h2><p>The SDK for .NET for the Gemini API is contained in the <code>Mscc.GenerativeAI</code> package. Install the dependency using dotnet CLI:</p><pre><code>dotnet add package Mscc.GenerativeAI</code></pre><p>See <a href="https://www.nuget.org/packages/Mscc.GenerativeAI/">README</a> for alternative options, like the NuGet Package Manager.</p><h2 id="initialize-the-generative-model">Initialize the Generative Model</h2><p>Before you can make any API calls, you need to add a reference to the namespace <code>Mscc.GenerativeAI</code> and initialize the Generative Model.</p><pre><code>using Mscc.GenerativeAI;

var googleAI = new GoogleAI(apiKey: Environment.GetEnvironmentVariable("GOOGLE_API_KEY");
var model = googleAI.GenerativeModel(model: Model.GeminiPro);</code></pre><h2 id="generate-text">Generate Text</h2><pre><code>var response = await model.GenerateContent("Write a story about a magic backpack.");
Console.WriteLine(response.Text);</code></pre><h2 id="what-s-next">What's next</h2><p>Explore the <a href="https://www.nuget.org/packages/Mscc.GenerativeAI/">README</a> of the NuGet package which has more samples documented. All unit tests are accessible in the <a href="https://github.com/mscraftsman/generative-ai">GitHub repository</a>:</p><figure class="kg-card kg-bookmark-card"><a class="kg-bookmark-container" href="https://github.com/mscraftsman/generative-ai"><div class="kg-bookmark-content"><div class="kg-bookmark-title">GitHub - mscraftsman/generative-ai: Gemini AI Client for .NET</div><div class="kg-bookmark-description">Gemini AI Client for .NET. Contribute to mscraftsman/generative-ai development by creating an account on GitHub.</div><div class="kg-bookmark-metadata"><img class="kg-bookmark-icon" src="https://github.githubassets.com/favicons/favicon.svg" alt="Quickstart: Use Gemini with .NET (Google AI)"><span class="kg-bookmark-author">GitHub</span><span class="kg-bookmark-publisher">mscraftsman</span></div></div><div class="kg-bookmark-thumbnail"><img src="https://opengraph.githubassets.com/75de26a26c206cf142204c77b13e5c9bcf75e72f9558f35bc27484c20585a4fe/mscraftsman/generative-ai" alt="Quickstart: Use Gemini with .NET (Google AI)"></div></a></figure><p>If you're new to generative AI models, you might want to look at the <a href="https://ai.google.dev/docs/concepts">concepts guide</a> and the <a href="https://ai.google.dev/docs/gemini_api_overview">Gemini API overview</a> before trying a quickstart.</p><!--kg-card-begin: html--><small>Image credit: Gemini using prompt <i>Create an image showing the fast start of a race in motor sport.</i></small><!--kg-card-end: html-->]]></content:encoded></item><item><title><![CDATA[NuGet: Better release notes and versioning]]></title><description><![CDATA[Release notes or better a Changelog is an important part of a package to inform other developers about new features, changes and fixes. Enjoy rich formatting and re-usable content for a NuGet package.]]></description><link>https://jochen.kirstaetter.name/nuget-better-release-notes-versioning/</link><guid isPermaLink="false">65e24044f2f01b106a424e3c</guid><category><![CDATA[Development]]></category><dc:creator><![CDATA[Jochen Kirstätter]]></dc:creator><pubDate>Sun, 31 Mar 2024 09:00:00 GMT</pubDate><media:content url="https://jochen.kirstaetter.name/content/images/2024/04/_913c222e-d6c8-4431-9586-3c2d42883014.jpeg" medium="image"/><content:encoded><![CDATA[<img src="https://jochen.kirstaetter.name/content/images/2024/04/_913c222e-d6c8-4431-9586-3c2d42883014.jpeg" alt="NuGet: Better release notes and versioning"><p>Providing release notes for a NuGet package is an essential part of the development and distribution of the package itself. Commonly it shall be the first source of information to describe latest updates regarding the improvements and changes.</p><p>However, the current way of authoring release notes in a .NET project is sub-optimal. The following approach might offer a simpler way to achieve this including formatting and additional purpose on GitHub.</p><h2 id="the-situation-you-might-be-facing-">The situation (you might be facing)</h2><p>On the one side, the Release notes element or <code>PackageReleaseNotes</code> of the MSBuild property in the <code>.csproj</code> project file is quite limited regarding formatting options. And it is cumbersome to update it with release information continuously. Especially while using the single line text entry in the properties page of Visual Studio. </p><p>Other the other hand, the <code>PackageReadmeFile</code> element provides a bit more freedom to describe a package, however, it is linked only. And on top of that, it is not even exposed in the user interface of the project properties.</p><p>So, having an <em>external</em> resource like a Markdown file that is not only linked could be an interesting alternative. The information is stored outside the project file, is easier to edit, and provides rich formatting options including images, bullet lists and hyperlinks. </p><h2 id="a-solution">A solution</h2><p>Luckily, similar to pushing a package to a network share or to a NuGet source feed we can leverage another MSBuild task to take the content of that Markdown file and inject it into the package description.</p><p><strong>Note:</strong> <em>For a code base that is hosted in a (public) repository on GitHub (or BitBucket, Azure DevOps, Google Cloud Source Repositories, etc) using <code>CHANGELOG.md</code> instead of release notes might be a better choice of file name. </em></p><p>Let's start with a fresh <code>CHANGELOG.md</code> that we place in the root of the project folder.</p><pre><code># Changelog (Release Notes)

All notable changes to this project will be documented in this file.

The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html) (SemVer).

## [Unreleased]

### Added
### Changed
### Fixed</code></pre><p>As you might see in the file content already we are following a suggested format to maintain the change log and we are establishing <a href="https://semver.org/spec/v2.0.0.html">Semantic Versioning</a> right from the beginning. The content is written in Markdown and apart from using your favourite IDE which might have an integrated viewer for Markdown it is a commonly used and understood formatting syntax among developers. Markdown can also be transformed to other output formats like HTML or PDF. Think of <code>pandoc</code> as a utility tool to generate a different output, or maybe any kind of static web page generator like Hugo, et al.</p><p>Now, with the <code>CHANGELOG.md</code> file in place (and under version control) it is time to use an MSBuild task to read the content of the file and inject it into the project properties. Add a new <code>Target</code> element in your <code>.csproj</code> file with the following content, probably near the bottom area.</p><pre><code>	&lt;Target Name="InjectPackageReleaseNotesFromFile" BeforeTargets="GenerateNuspec" Condition="Exists('CHANGELOG.md')"&gt;
		&lt;PropertyGroup&gt;
			&lt;PackageReleaseNotes&gt;$([System.IO.File]::ReadAllText("$(MSBuildProjectDirectory)/CHANGELOG.md"))&lt;/PackageReleaseNotes&gt;
		&lt;/PropertyGroup&gt;
	&lt;/Target&gt;</code></pre><p>According to the <code>BeforeTarget</code> attribute this task is executed before generating the NuGet specification file <code>.nuspec</code>. A process that happens after successful compilation of the project or solution and as the name suggests before the actual NuGet package is created. Sounds perfect.</p><p>The task itself creates or updates the XML element <code>PackageReleaseNotes</code> in the project file and replaces the value with the complete content of the <code>CHANGELOG.md</code> file. To avoid any compilation issues the <code>Condition</code> attributes checks for the existence of the referenced file prior to executing the task.</p><p>To keep yourself and maybe other team members informed, place the following remark in the original Release notes of the project properties.</p><pre><code>&lt;PackageReleaseNotes&gt;(Package release notes are in CHANGELOG.md)&lt;/PackageReleaseNotes&gt;</code></pre><p>Alternatively, leave it blank.</p><h2 id="the-result">The result</h2><p>Using Markdown to create richly formatted release notes compared to plain text might be a welcoming piece of documentation. </p><p>Here's how it looks in the NuGet Gallery.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://jochen.kirstaetter.name/content/images/2024/04/image.png" class="kg-image" alt="NuGet: Better release notes and versioning" srcset="https://jochen.kirstaetter.name/content/images/size/w600/2024/04/image.png 600w, https://jochen.kirstaetter.name/content/images/2024/04/image.png 888w" sizes="(min-width: 720px) 720px"><figcaption>NuGet doesn't have a Markdown viewer but links are clickable</figcaption></figure><p>In comparison the same release notes on GitHub.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://jochen.kirstaetter.name/content/images/2024/04/image-1.png" class="kg-image" alt="NuGet: Better release notes and versioning" srcset="https://jochen.kirstaetter.name/content/images/size/w600/2024/04/image-1.png 600w, https://jochen.kirstaetter.name/content/images/2024/04/image-1.png 971w" sizes="(min-width: 720px) 720px"><figcaption>Rich formatted release notes with hyperlinks</figcaption></figure><p>With a small amount of extra work same <code>CHANGELOG.md</code> could be used as a source of <a href="https://pages.github.com/">GitHub Pages</a> and be part of a generated, static website of your project.</p><h2 id="what-s-got-that-to-do-with-versioning">What's got that to do with versioning?</h2><p>The change log is already using semantic versioning to document changes. So, while already using this approach to inject the release notes into the NuGet package... Why not doing the same for the version of the package.</p><p>Instead of fiddling around in the project properties or updating the <code>.csproj</code> file directly, wouldn't be better to have a <code>VERSION</code> file in the root folder and its content is replacing the <code>Version</code> element during the compilation process.</p><p>Put the following lines once in your project file, and it's done.</p><pre><code>&lt;Version&gt;$([System.IO.File]::ReadAllText("$(MSBuildProjectDirectory)/../../VERSION"))&lt;/Version&gt;	</code></pre><p>The path might be different for you and depending on how you structured your project. I put that <code>VERSION</code> file into the root folder of the repository because I'm using it for multiple projects simultaneously. A lazy way to keep the version information of related projects / packages in the same solution synchronized.</p><p>Both approaches - <code>CHANGELOG.md</code> and <code>VERSION</code> - are used in the NuGet packages <code>Mscc.GenerativeAI*</code>. It's an open-source library to integrate Google Gemini into .NET applications. </p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://jochen.kirstaetter.name/content/images/2024/04/image-2.png" class="kg-image" alt="NuGet: Better release notes and versioning" srcset="https://jochen.kirstaetter.name/content/images/size/w600/2024/04/image-2.png 600w, https://jochen.kirstaetter.name/content/images/2024/04/image-2.png 908w" sizes="(min-width: 720px) 720px"><figcaption>Synchronized package versions thanks to injection during compilation</figcaption></figure><p>The repository of <a href="https://github.com/mscraftsman/generative-ai">Gemini AI Client for .NET and ASP.NET Core</a> is hosted on GitHub.</p><h2 id="final-thought">Final thought</h2><p>Apart from maintaining those two files in the repository manually, they could have been generated or updated automatically by a continuous integration (CI) pipeline. </p><p>However, I leave that to you. </p><p>Perhaps a future blog article, who knows...</p><!--kg-card-begin: html--><small>Image credit: Image Creator from Microsoft Designer using prompt: <i>Create an image depicting versioning of packages</i></small><!--kg-card-end: html-->]]></content:encoded></item><item><title><![CDATA[Automate NuGet package creation using Google Build]]></title><description><![CDATA[Taking multiple steps to build, pack and publish a NuGet package manually is a distraction and error-prone. Use Google Cloud Build to handle the boring parts of the SDLC.]]></description><link>https://jochen.kirstaetter.name/automate-nuget-package-creation-google-build/</link><guid isPermaLink="false">65e1ae16f2f01b106a424cc5</guid><category><![CDATA[Development]]></category><dc:creator><![CDATA[Jochen Kirstätter]]></dc:creator><pubDate>Mon, 04 Mar 2024 13:35:00 GMT</pubDate><media:content url="https://jochen.kirstaetter.name/content/images/2024/03/Gemini_Generated_Image-1-.jpeg" medium="image"/><content:encoded><![CDATA[<img src="https://jochen.kirstaetter.name/content/images/2024/03/Gemini_Generated_Image-1-.jpeg" alt="Automate NuGet package creation using Google Build"><p>In a previous article on <a href="https://jochen.kirstaetter.name/create-nuget-packages-vs-code/">Create NuGet packages with Visual Studio / Visual Studio Code</a> the software development lifecycle (SDLC) from build, pack, and deployment is done manually. Which can be quite time-consuming, tedious and tends to be error-prone given human interaction necessary. How about automating that process completely using Google Build?</p><h2 id="what-s-google-build">What's Google Build?</h2><p>Shortly said, <a href="https://cloud.google.com/build">Cloud Build</a> is a service that executes your builds on Google Cloud. Or perhaps more precisely.</p><blockquote>Cloud Build, Google Cloud’s continuous integration (CI) and continuous delivery (CD) platform, lets you build software quickly across all languages.</blockquote><p>There are various machine types available and you can create a private pool for specific machine configurations or requirements.</p><p>The interesting part for single developers and probably small(er) teams is that Google Build offers a free tier which includes 2,500 build-minutes (at the time of writing) which can be used to automate quite some tasks.</p><p>Learn more about <a href="https://cloud.google.com/build/pricing">Google Cloud Build Pricing</a>.</p><h2 id="how-to-get-started">How to get started?</h2><p>Navigate to Google Cloud Console, select your project and then enable the Google Build API for that project (and associated billing account).</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://jochen.kirstaetter.name/content/images/2024/03/Screenshot-from-2024-03-01-20-14-19.png" class="kg-image" alt="Automate NuGet package creation using Google Build" srcset="https://jochen.kirstaetter.name/content/images/size/w600/2024/03/Screenshot-from-2024-03-01-20-14-19.png 600w, https://jochen.kirstaetter.name/content/images/size/w1000/2024/03/Screenshot-from-2024-03-01-20-14-19.png 1000w, https://jochen.kirstaetter.name/content/images/2024/03/Screenshot-from-2024-03-01-20-14-19.png 1235w" sizes="(min-width: 720px) 720px"><figcaption>Enable the Google Build API in Google Cloud Console&nbsp;</figcaption></figure><p>Or if you prefer to use the <code>gcloud</code> CLI tool run the following command.</p><pre><code class="language-bash">gcloud services enable cloudbuild.googleapis.com</code></pre><p>If you are prompted to authorize the gcloud CLI, enter your credentials. Once the API is enabled, you can use the gcloud CLI to manage your builds. For example, to create a build, run the following command:</p><pre><code class="language-bash">gcloud builds submit --config cloudbuild.yaml	</code></pre><p>Which gives us the next glue. We need a build configuration file that instructs Google Build what to do. A basic build configuration file is described in the documentation: <a href="https://cloud.google.com/build/docs/configuring-builds/create-basic-configuration">Create a build configuration file</a>.</p><h2 id="use-build-configuration-file">Use build configuration file</h2><p>Writing such a build configuration file from scratch manually would be quite time consuming and probably a journey of trials and errors. Let Duet AI do the boring parts for us.</p><blockquote>How to use Google Build to automate the build process?</blockquote><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://jochen.kirstaetter.name/content/images/2024/03/Screenshot-from-2024-03-01-20-33-55.png" class="kg-image" alt="Automate NuGet package creation using Google Build" srcset="https://jochen.kirstaetter.name/content/images/size/w600/2024/03/Screenshot-from-2024-03-01-20-33-55.png 600w, https://jochen.kirstaetter.name/content/images/size/w1000/2024/03/Screenshot-from-2024-03-01-20-33-55.png 1000w, https://jochen.kirstaetter.name/content/images/2024/03/Screenshot-from-2024-03-01-20-33-55.png 1160w" sizes="(min-width: 720px) 720px"><figcaption>Duet AI gets the build configuration file done within seconds.</figcaption></figure><h3 id="build-pack-and-push">Build, pack and push</h3><figure class="kg-card kg-code-card"><pre><code class="language-yaml">steps:
- name: 'gcr.io/cloud-builders/dotnet'
  args: ['build', '-c', 'Release', 'src/Mscc.GenerativeAI.csproj']
- name: 'gcr.io/cloud-builders/dotnet'
  args: ['pack', '-c', 'Release', 'src/Mscc.GenerativeAI.csproj', '-o', 'output/']
- name: 'gcr.io/cloud-builders/dotnet'
  args: ['nuget', 'push', 'output/*.nupkg', '-k', '${_NUGET_API_KEY}', '-s', 'https://api.nuget.org/v3/index.json']

options:
  substitutions:
    _NUGET_API_KEY: YOUR_NUGET_API_KEY
</code></pre><figcaption>The generated <code>cloudbuild.yaml</code> file located in the project's root folder</figcaption></figure><p>Those are exactly the steps we did manually previously.</p><ol><li>Build the .NET solution in <code>Release</code> configuration</li><li>Pack and put the assembly into the <code>output</code> folder</li><li>Push the generated package to NuGet using an API key</li></ol><p>That's a solid fundament and I didn't have to look up the name of the <a href="https://cloud.google.com/build/docs/cloud-builders">cloud builder</a>. Cloud builders are <a href="https://cloud.google.com/containers">container images</a> with common languages and tools installed in them. </p><p>Meaning, we are effectively pulling a Docker image by its container name from Google's Container Registry and use it to execute the arguments specified. The source code for these builders is available in the <a href="https://github.com/GoogleCloudPlatform/cloud-builders">cloud builders GitHub repository</a>. The Cloud Build developer community provides additional <a href="https://github.com/GoogleCloudPlatform/cloud-builders-community">open-source builders</a> that you can use to execute your tasks. And lastly, you can create your own custom builder for use in your builds.</p><h3 id="a-few-options">A few options</h3><p>As part of the <code>options</code> section you could also specify the <code>machineType</code> used to run those steps. The <a href="https://cloud.google.com/build/pricing">default machine type</a> is <code>e2-standard-2</code> with 2 CPUs. Which should be sufficient for the majority of build tasks and is also covered by the free tier of Google Build mentioned at the beginning.</p><p>Now, the final part of the build config file is the value of the NuGet API key, and how it can be <em>injected</em> into the build process. <a href="https://cloud.google.com/build/docs/configuring-builds/substitute-variable-values">Substituting variable values</a> can be achieved in different ways. There is a list of default substitutions, the possibility to work with user-defined substitutions, and even dynamic substitutions which are evaluated during the building process.</p><h2 id="submit-to-google-build">Submit to Google Build</h2><p>Again, asking Duet AI.</p><blockquote>How do I submit this configuration to Google Build with substitutions?</blockquote><p>To submit your build configuration file to Google Build, you can use the <code>gcloud builds submit</code> command. The following command will submit the build configuration file that you have provided to Google Build:</p><pre><code class="language-bash">gcloud builds submit --config cloudbuild.yaml --substitutions _NUGET_API_KEY=YOUR_NUGET_API_KEY
</code></pre><p>This command will start a build using the configuration that you have provided, with the substitution <code>_NUGET_API_KEY</code> set to the value <code>YOUR_NUGET_API_KEY</code>. You can track the progress of your build by using the <code>gcloud builds list</code> command. Here's an interesting part of the build process.</p><pre><code class="language-bash">Starting Step #1
Step #1: Already have image (with digest): gcr.io/cloud-builders/dotnet
Step #1: Microsoft (R) Build Engine version 16.2.37902+b5aaefc9f for .NET Core
Step #1: Copyright (C) Microsoft Corporation. All rights reserved.
Step #1: 
Step #1:   Restore completed in 322.89 ms for /workspace/src/Mscc.GenerativeAI.csproj.
Step #1: /usr/share/dotnet/sdk/2.1.818/Microsoft.Common.CurrentVersion.targets(1175,5): error MSB3644: The reference assemblies for .NETFramework,Version=v4.7.2 were not found. To resolve this, install the Developer Pack (SDK/Targeting Pack) for this framework version or retarget your application. You can download .NET Framework Developer Packs at https://aka.ms/msbuild/developerpacks [/workspace/src/Mscc.GenerativeAI.csproj]
Finished Step #1
ERROR
ERROR: build step 1 "gcr.io/cloud-builders/dotnet" failed: step exited with non-zero status: 1
</code></pre><p>Given the .NET versions used the default container image is going to fail. Why?</p><p>Because it is based on the SDK for .NET Core 2.1! See <a href="https://github.com/GoogleCloudPlatform/cloud-builders/tree/master/dotnet">GitHub</a></p><p>The project used targets newer .NET versions, and so we need a newer Docker image that we can retrieve from the Microsoft Container Registry (MCR). So, to migrate to the official <code>dotnet</code> image, make the following changes to your <code>cloudbuild.yaml</code>:</p><figure class="kg-card kg-code-card"><pre><code class="language-yaml">- name: 'gcr.io/cloud-builders/dotnet'
+ name: 'mcr.microsoft.com/dotnet/sdk:8.0'
+ entrypoint: 'dotnet'
</code></pre><figcaption>Use the official .NET 8.0 SDK Docker image</figcaption></figure><p>Remove the original cloud builder provided by Google Container Registry (GCR) and add the most recent Docker image with .NET 8.0 SDK from the MCR.</p><p>The updated build config file looks like so.</p><figure class="kg-card kg-code-card"><pre><code class="language-yaml">steps:
# Build the project
- name: 'mcr.microsoft.com/dotnet/sdk:8.0'
  entrypoint: 'dotnet'
  args: ['build', '-c', 'Release', 'src/Mscc.GenerativeAI.csproj']
# Pack the NuGet package
- name: 'mcr.microsoft.com/dotnet/sdk:8.0'
  entrypoint: 'dotnet'

... skipped for brevity</code></pre><figcaption>Updated choice of Docker container from the MCR</figcaption></figure><p>Which returns the expected outcome.</p><pre><code class="language-bash">... skipped for brevity
Step #0:   Mscc.GenerativeAI -&gt; /workspace/src/bin/Release/net8.0/Mscc.GenerativeAI.dll
Step #0:   Successfully created package '/workspace/src/bin/Release/Mscc.GenerativeAI.0.4.4.nupkg'.
Step #0: 
Step #0: Build succeeded.
Step #0: 

... skipped for brevity

Step #0:     142 Warning(s)
Step #0:     0 Error(s)
Step #0: 
Step #0: Time Elapsed 00:00:20.87
Finished Step #0
Starting Step #1
Step #1: Already have image (with digest): mcr.microsoft.com/dotnet/sdk:8.0
Step #1: MSBuild version 17.9.4+90725d08d for .NET
Step #1:   Determining projects to restore...
Step #1:   All projects are up-to-date for restore.
Step #1:   Successfully created package '/workspace/output/Mscc.GenerativeAI.0.4.4.nupkg'.
Finished Step #1
Starting Step #2
Step #2: Already have image (with digest): mcr.microsoft.com/dotnet/sdk:8.0
Step #2: Pushing Mscc.GenerativeAI.0.4.4.nupkg to 'https://www.nuget.org/api/v2/package'...
Step #2:   PUT https://www.nuget.org/api/v2/package/
Step #2:   Created https://www.nuget.org/api/v2/package/ 742ms
Step #2: Your package was pushed.
Finished Step #2
PUSH
DONE
</code></pre><p>A successfully completed build, pack and push of the NuGet package.</p><h2 id="tune-the-build-config-file">Tune the build config file</h2><p>While using the <code>dotnet</code> Docker image to build, pack and push the NuGet package we might want to reduce the generated output a little bit. In particular regarding the first time experience and telemetry opt-out. Therefore, add the following <code>env</code> block into the <code>options</code>.</p><pre><code class="language-yaml">options:
  env:
  - 'DOTNET_CLI_TELEMETRY_OPTOUT=true'
  - 'DOTNET_SKIP_FIRST_TIME_EXPERIENCE=true'
</code></pre><p>The resulting build configuration file should look similar to this.</p><pre><code class="language-yaml"># outline the steps to build a .NET project, pack it as Nuget package and push it to Nuget source feed
steps:
# Build the project
- name: 'mcr.microsoft.com/dotnet/sdk:8.0'
  entrypoint: 'dotnet'
  args: ['build', '-c', 'Release', 'src/Mscc.GenerativeAI.csproj']
# Pack the NuGet package
- name: 'mcr.microsoft.com/dotnet/sdk:8.0'
  entrypoint: 'dotnet'
  args: ['pack', '-c', 'Release', 'src/Mscc.GenerativeAI.csproj', '-o', 'output/']
# Push the package to NuGet source feed
- name: 'mcr.microsoft.com/dotnet/sdk:8.0'
  entrypoint: 'dotnet'
  args: ['nuget', 'push', 'output/*.nupkg', '-k', '${_NUGET_API_KEY}', '-s', 'https://api.nuget.org/v3/index.json']

options:
  substitutionOption: 'ALLOW_LOOSE'
  env:
  - 'DOTNET_CLI_TELEMETRY_OPTOUT=true'
  - 'DOTNET_SKIP_FIRST_TIME_EXPERIENCE=true'
substitutions:
  _NUGET_API_KEY: YOUR_NUGET_API_KEY
</code></pre><p>Eventually, it is considerable to use a separate API key for NuGet specifically used for the Google Build submission compared to the one used while doing it manually. I have several API keys in place.</p><h2 id="where-s-the-actual-automation">Where's the actual automation?</h2><p>Up till now, we have reduced manual labour by using a scripted approach. However, there is no automated process, at least not yet. To achieve an automated publication of a NuGet package we need a trigger. A trigger would initiate the Google Build submission based on a specific interaction, like say pushing a commit to the repository, merging a pull request, or perhaps run at a certain time every day.</p><blockquote>Cloud Build uses build triggers to enable CI/CD automation. You can configure triggers to listen for incoming events, such as when a new commit is pushed to a repository or when a pull request is initiated, and then automatically execute a build when new events come in.</blockquote><p>Create a <a href="https://cloud.google.com/build/docs/triggers">Cloud Trigger</a> to start an automated Cloud Build whenever there are changes to the source code. For that, we need to know where the code repository is located and establish a connection in Cloud Build. Your repositories in Cloud Source Repositories are connected to Cloud Build by default. If you are connecting an external repository, such as one hosted on GitHub or Bitbucket, you will need admin-level permissions on the repository to initially connect your repository to Cloud Build.</p><p>Learn more about <a href="https://cloud.google.com/build/docs/automating-builds/create-manage-triggers#gcloud">Create and manage build triggers</a>.</p><h3 id="connect-a-github-repository">Connect a GitHub repository</h3><p>The sample source code is hosted on GitHub. This gives us two options, either we add a new remote to our local workspace and mirror the source code, or we create a trigger with a connection to the GitHub repository. Let's go for the connection.</p><p>Open the Triggers section of Cloud Build in the Google Cloud Console.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://jochen.kirstaetter.name/content/images/2024/03/Screenshot-from-2024-03-03-09-45-47.png" class="kg-image" alt="Automate NuGet package creation using Google Build" srcset="https://jochen.kirstaetter.name/content/images/size/w600/2024/03/Screenshot-from-2024-03-03-09-45-47.png 600w, https://jochen.kirstaetter.name/content/images/2024/03/Screenshot-from-2024-03-03-09-45-47.png 964w" sizes="(min-width: 720px) 720px"><figcaption>Cloud Build needs a trigger to start automatically</figcaption></figure><p>Click on Connect Repository in the top area and complete the connection.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://jochen.kirstaetter.name/content/images/2024/03/image.png" class="kg-image" alt="Automate NuGet package creation using Google Build" srcset="https://jochen.kirstaetter.name/content/images/size/w600/2024/03/image.png 600w, https://jochen.kirstaetter.name/content/images/2024/03/image.png 733w" sizes="(min-width: 720px) 720px"><figcaption>Select the source code management provider</figcaption></figure><p>In case of first connection, GitHub asks for your consent to authorize Google Cloud Build to access your repositories.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://jochen.kirstaetter.name/content/images/2024/03/image-1.png" class="kg-image" alt="Automate NuGet package creation using Google Build" srcset="https://jochen.kirstaetter.name/content/images/size/w600/2024/03/image-1.png 600w, https://jochen.kirstaetter.name/content/images/size/w1000/2024/03/image-1.png 1000w, https://jochen.kirstaetter.name/content/images/2024/03/image-1.png 1099w" sizes="(min-width: 720px) 720px"><figcaption>Grant permissions to Cloud Build and authorize access to repositories</figcaption></figure><p>Eventually, the list of repositories on GitHub might be incomplete.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://jochen.kirstaetter.name/content/images/2024/03/image-2.png" class="kg-image" alt="Automate NuGet package creation using Google Build" srcset="https://jochen.kirstaetter.name/content/images/size/w600/2024/03/image-2.png 600w, https://jochen.kirstaetter.name/content/images/2024/03/image-2.png 713w"><figcaption>Select the repository to connect to from GitHub</figcaption></figure><p>Click on Edit repositories on GitHub to extend the Repository access.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://jochen.kirstaetter.name/content/images/2024/03/image-3.png" class="kg-image" alt="Automate NuGet package creation using Google Build" srcset="https://jochen.kirstaetter.name/content/images/size/w600/2024/03/image-3.png 600w, https://jochen.kirstaetter.name/content/images/size/w1000/2024/03/image-3.png 1000w, https://jochen.kirstaetter.name/content/images/2024/03/image-3.png 1279w" sizes="(min-width: 720px) 720px"><figcaption>Adjust repository access, if needed</figcaption></figure><p>After adding the target repository, we can establish the connection to use in Cloud Build.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://jochen.kirstaetter.name/content/images/2024/03/image-4.png" class="kg-image" alt="Automate NuGet package creation using Google Build" srcset="https://jochen.kirstaetter.name/content/images/size/w600/2024/03/image-4.png 600w, https://jochen.kirstaetter.name/content/images/2024/03/image-4.png 709w"><figcaption>Connect to the repository on GitHub</figcaption></figure><h3 id="create-a-cloud-trigger">Create a Cloud Trigger</h3><p>Last, we create a trigger using the connection. You can accept the suggested one at the end of the connection or create a new trigger.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://jochen.kirstaetter.name/content/images/2024/03/image-5.png" class="kg-image" alt="Automate NuGet package creation using Google Build" srcset="https://jochen.kirstaetter.name/content/images/size/w600/2024/03/image-5.png 600w, https://jochen.kirstaetter.name/content/images/2024/03/image-5.png 721w" sizes="(min-width: 720px) 720px"><figcaption>Optionally, create a sample trigger given suggestion</figcaption></figure><p>Click on Create sample trigger and you are done.</p><p>Out of laziness I created the sample trigger but I'm going to edit it directly afterwards. Why? Because I don't like the suggested name,  the suggested description, I don't want the trigger to monitor every branch but the <code>main</code>, and most importantly the substitution variables are missing.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://jochen.kirstaetter.name/content/images/2024/03/image-9.png" class="kg-image" alt="Automate NuGet package creation using Google Build" srcset="https://jochen.kirstaetter.name/content/images/size/w600/2024/03/image-9.png 600w, https://jochen.kirstaetter.name/content/images/2024/03/image-9.png 726w" sizes="(min-width: 720px) 720px"><figcaption>Add any substitution variables needed to run the Cloud Build configuration</figcaption></figure><p>The following <code>gcloud</code> command creates the same trigger including the user-defined substitutions.</p><pre><code class="language-bash">    gcloud builds triggers create github \
    --name="nuget-build-push" \
    --description="Build, pack and push to NuGet on main branch" \
    --region="us-central1" \
    --repo-name="generative-ai" \
    --repo-owner="mscraftsman" \
    --branch-pattern="^main$" \
    --build-config="cloudbuild.yaml" \
    --substitutions="_NUGET_API_KEY=YOUR_NUGET_API_KEY"
</code></pre><p>The result should look like this.</p><pre><code class="language-bash">Created [https://cloudbuild.googleapis.com/v1/projects/...].
NAME              CREATE_TIME                STATUS
nuget-build-push  2024-03-03T06:44:22+00:00</code></pre><p>Learn more about <a href="https://cloud.google.com/build/docs/automating-builds/create-manage-triggers#gcloud">Create and manage build triggers</a>.</p><h2 id="showtime-">Showtime!</h2><p>I made some changes to my source code and I'm about to push those commits.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://jochen.kirstaetter.name/content/images/2024/03/image-10.png" class="kg-image" alt="Automate NuGet package creation using Google Build"><figcaption>Ready to push commits to the remote repository</figcaption></figure><p>After click on Sync Changes, I open the History section of Cloud Build to check the status.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://jochen.kirstaetter.name/content/images/2024/03/image-12.png" class="kg-image" alt="Automate NuGet package creation using Google Build" srcset="https://jochen.kirstaetter.name/content/images/size/w600/2024/03/image-12.png 600w, https://jochen.kirstaetter.name/content/images/2024/03/image-12.png 939w" sizes="(min-width: 720px) 720px"><figcaption>Spinning status indicates an active build is running</figcaption></figure><p>You can directly observe the build steps and see the result of each in the details of a build.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://jochen.kirstaetter.name/content/images/2024/03/image-13.png" class="kg-image" alt="Automate NuGet package creation using Google Build" srcset="https://jochen.kirstaetter.name/content/images/size/w600/2024/03/image-13.png 600w, https://jochen.kirstaetter.name/content/images/size/w1000/2024/03/image-13.png 1000w, https://jochen.kirstaetter.name/content/images/2024/03/image-13.png 1261w" sizes="(min-width: 720px) 720px"><figcaption>Automated NuGet package build, pack and push</figcaption></figure><p>The substitution variables, here the NuGet API key, have been applied and the package has been pushed to nuget.org successfully.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://jochen.kirstaetter.name/content/images/2024/03/image-14.png" class="kg-image" alt="Automate NuGet package creation using Google Build" srcset="https://jochen.kirstaetter.name/content/images/size/w600/2024/03/image-14.png 600w, https://jochen.kirstaetter.name/content/images/size/w1000/2024/03/image-14.png 1000w, https://jochen.kirstaetter.name/content/images/2024/03/image-14.png 1187w" sizes="(min-width: 720px) 720px"><figcaption>Published package produced by Google Cloud Build</figcaption></figure><p>Now with a complete, working CI/CD pipeline using Google Cloud Build, I can concentrate on the source code and the implementation of new features. Gone are the boring and error-prone, manual steps to build, pack and push a new version of the NuGet package.</p><p>What a breeze!</p><p>But there is more...</p><h2 id="avoid-too-many-builds">Avoid too many builds</h2><p>There are reasons you don't want to trigger a new build automatically, like i.e. fixing a typo, amending the documentation, or adding a new test, etc. Any kind of changes to the repository that would not justify / satisfy the deployment of a new version of a NuGet package.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://jochen.kirstaetter.name/content/images/2024/03/Screenshot-from-2024-03-03-14-54-51.png" class="kg-image" alt="Automate NuGet package creation using Google Build" srcset="https://jochen.kirstaetter.name/content/images/size/w600/2024/03/Screenshot-from-2024-03-03-14-54-51.png 600w, https://jochen.kirstaetter.name/content/images/2024/03/Screenshot-from-2024-03-03-14-54-51.png 793w" sizes="(min-width: 720px) 720px"><figcaption>Last two commits (marked in red) did not trigger a build (marked in green)</figcaption></figure><p>Triggers in Cloud Build provide at least two ways to reduce unnecessary builds and avoid wasting valuable build-minutes in your billing account.</p><h3 id="use-files-filter">Use files filter</h3><p>In such case, you can either specify an <code>Included files filter</code> or an <code>Ignored files filter</code> using <a href="https://en.wikipedia.org/wiki/Glob_(programming)">glob strings</a> to define which files need to be affected or shall be ignored to trigger a build.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://jochen.kirstaetter.name/content/images/2024/03/image-16.png" class="kg-image" alt="Automate NuGet package creation using Google Build" srcset="https://jochen.kirstaetter.name/content/images/size/w600/2024/03/image-16.png 600w, https://jochen.kirstaetter.name/content/images/2024/03/image-16.png 716w"><figcaption>Filters control which changes affecting files will trigger builds</figcaption></figure><p>The corresponding <code>gcloud</code> options are called <code>--included-files</code> and <code>ignored-files</code> to manage when a build is triggered or not.</p><p>The structure of my public GitHub <a href="https://github.com/mscraftsman/generative-ai">generative-ai</a> used here in the article, has a folder called <code>src</code> that contains the source code of the actual NuGet package. With an included files filter of <code>src/**</code> I define that only changes affecting at least one included file will trigger a build. </p><p><strong>Note:</strong> <em><code>**</code> is a recursive version of <code>*</code> which matches all files and directories in the selected directory and its subdirectories.</em></p><h3 id="skipping-a-build-trigger">Skipping a build trigger</h3><p>Additionally, there is the ability to skip a build trigger based on a single commit message. In such scenarios, you can include <code>[skip ci]</code> or <code>[ci skip]</code> in the commit message, and a build will not be invoked.</p><p>If you want to run a build on that commit later, use the <strong>Run trigger</strong> button in the <a href="https://console.cloud.google.com/cloud-build/triggers">Triggers</a> page.</p><p>Learn more about <a href="https://cloud.google.com/build/docs/automating-builds/create-manage-triggers">Cloud Build triggers</a>.</p><!--kg-card-begin: html--><small>Image credit: Gemini using prompt "an image showing the creation of packages"</small><!--kg-card-end: html-->]]></content:encoded></item><item><title><![CDATA[Create NuGet packages with Visual Studio / Visual Studio Code]]></title><description><![CDATA[An essential tool for any modern development platform is a mechanism through which developers can create, share, and consume useful code. For .NET it's NuGet packages to the rescue!]]></description><link>https://jochen.kirstaetter.name/create-nuget-packages-vs-code/</link><guid isPermaLink="false">6030cbdad049a45a89bdfa44</guid><category><![CDATA[Development]]></category><dc:creator><![CDATA[Jochen Kirstätter]]></dc:creator><pubDate>Fri, 01 Mar 2024 10:34:57 GMT</pubDate><media:content url="https://jochen.kirstaetter.name/content/images/2024/03/Gemini_Generated_Image.jpeg" medium="image"/><content:encoded><![CDATA[<img src="https://jochen.kirstaetter.name/content/images/2024/03/Gemini_Generated_Image.jpeg" alt="Create NuGet packages with Visual Studio / Visual Studio Code"><p>Using NuGet packages gives developers a great amount of flexibility and fast pace to implement their own ideas. Whether you are using packages from other authors or prefer to use your own ones. The following article summarises my findings in how to get started building NuGet packages with Visual Studio, Visual Studio Code, or even the command line only.</p><p>During one of the last assignments and more recently working on some Gemini AI related coding I came across the need for NuGet packages.</p><h2 id="what-is-nuget">What is NuGet?</h2><p>An essential tool for any modern development platform is a mechanism through which developers can create, share, and consume useful code. Often such code is bundled into "packages" that contain compiled code (as DLLs) along with other content needed in the projects that consume these packages.</p><p>For more background information I highly recommend reading <a href="https://blog.davidebbo.com/2011/01/nuget-versioning-part-1-taking-on-dll.html">Taking on DLL hell</a> and follow-up articles by David Ebbo.</p><p>For .NET (including .NET Core), the Microsoft-supported mechanism for sharing code is <strong>NuGet</strong>, which defines how packages for .NET are created, hosted, and consumed, and <a href="https://learn.microsoft.com/en-us/nuget/install-nuget-client-tools">provides the tools</a> for each of those roles.</p><p>Following is the flow of NuGet package.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://jochen.kirstaetter.name/content/images/2024/02/image-11.png" class="kg-image" alt="Create NuGet packages with Visual Studio / Visual Studio Code" srcset="https://jochen.kirstaetter.name/content/images/size/w600/2024/02/image-11.png 600w, https://jochen.kirstaetter.name/content/images/2024/02/image-11.png 719w"><figcaption>The flow of packages between creators, hosts, and consumers</figcaption></figure><p>Learn more <a href="https://learn.microsoft.com/en-us/nuget/what-is-nuget">about NuGet in the documentation</a>.</p><p>Although there are multiple tools to handle NuGet packages this article is mainly focusing on the <code>dotnet</code> CLI tool.</p><h2 id="creating-a-new-project">Creating a new project</h2><p>Whether you start with a clean slate or converting/extending an existing project is nearly the same experience. For clarity I'm going to create a new <code>dotnet</code> project and guide you through the steps to add more functionality to the NuGet package.</p><pre><code>dotnet new classlib</code></pre><p>Despite having no functionality it is already possible to create a NuGet package using such an empty project.</p><pre><code>dotnet pack</code></pre><p>However, you would be stuck with the default values for the moment. Which we won't accept.</p><blockquote>"Don't accept the defaults!" – Abel Wang</blockquote><p>The command output has the full path information to the generated <code>.nupkg</code> file. Which is a ZIP archive and can be inspected either using an archive manager or the built-in features of the file manager.</p><h2 id="targeting-a-net-version">Targeting a .NET version</h2><p>While creating a new project you either use the target versions of .NET or the project template defines it for you. When you open a .NET project file, usually a <code>csproj</code> file for C# you might notice the XML element <code>TargetFramework</code>.</p><pre><code>&lt;Project Sdk="Microsoft.NET.Sdk"&gt; 
  &lt;PropertyGroup&gt; 
    &lt;TargetFramework&gt;netstandard2.0&lt;/TargetFramework&gt; 
  &lt;/PropertyGroup&gt; 
&lt;/Project&gt;</code></pre><p>The allowed value of <code>TargetFramework</code> are .NET specific version moniker and instructs the compiler which version of .NET to target for your assembly.</p><h2 id="multi-targeting-net-versions">Multi-targeting .NET versions</h2><p>You have seen it already with numerous other NuGet packages that are targetting multiple versions of .NET. Ranging from elderly versions of .NET Framework, and therefore Windows only, to the latest preview versions of .NET (Core). How is this done? Using .NET ability to allow targetting multiple versions using one single project.</p><p>Open your .NET project <code>.csproj</code> file and change the <code>TargetFramework</code> element to its plural version <code>TargetFrameworks</code> and add more <a href="https://learn.microsoft.com/en-us/nuget/reference/target-frameworks">target framework monikers</a> (TFM) separated by semicolons, like so.</p><pre><code>&lt;Project Sdk="Microsoft.NET.Sdk"&gt; 
  &lt;PropertyGroup&gt; 
    &lt;TargetFrameworks&gt;netstandard2.0;net8.0&lt;/TargetFrameworks&gt; 
  &lt;/PropertyGroup&gt; 
&lt;/Project&gt;</code></pre><p>Learn more about <a href="https://learn.microsoft.com/en-us/nuget/create-packages/supporting-multiple-target-frameworks">multi-targetting for NuGet packages</a> and how to <a href="https://learn.microsoft.com/en-us/nuget/create-packages/multiple-target-frameworks-project-file">support multiple .NET versions in your project file</a>.</p><h2 id="package-attributes-in-your-project-file">Package attributes in your project file</h2><p>There are a number of attributes for NuGet packages that can be added to the project file. Newer versions of Visual Studio (2022 and onwards) provide better options and most of those values can be configured in the IDE under the properties of the project.</p><p>As we are using MSBuild to pack the assembly and create the NuGet package, we use MSBuild properties to configure and describe the attributes of the package. Let's have a look at some essential MSBuild properties which might cover the majority of needs.</p><pre><code>&lt;Project Sdk="Microsoft.NET.Sdk"&gt; 
  &lt;PropertyGroup&gt; 
    &lt;TargetFramework&gt;netstandard2.0&lt;/TargetFramework&gt; 
    &lt;PackageId&gt;MSCC.GenerativeAI&lt;/PackageId&gt; 
    &lt;Version&gt;0.5.42&lt;/Version&gt; 
    &lt;Description&gt; 
      A simple package to integrate generative AI into an application. 
    &lt;/Description&gt; 
   &lt;PackageProjectUrl&gt;https://mscraftsman.github.io/&lt;/PackageProjectUrl&gt; 
    &lt;RepositoryUrl&gt;https://github.com/mscraftsman/generative-ai&lt;/RepositoryUrl&gt; 
    &lt;Authors&gt;Jochen Kirstätter&lt;/Authors&gt; 
    &lt;Copyright&gt;Copyright (c) Jochen Kirstätter&lt;/Copyright&gt; 
    &lt;PackageReadmeFile&gt;README.md&lt;/PackageReadmeFile&gt; 
    &lt;PackageIcon&gt;mscc-nuget.png&lt;/PackageIcon&gt; 
    &lt;PackageTags&gt;genAI;Generative AI;Gemini;Vertex AI&lt;/PackageTags&gt; 
    &lt;PackageLicenseFile&gt;LICENSE&lt;/PackageLicenseFile&gt; 
    &lt;PackageRequireLicenseAcceptance&gt;False&lt;/PackageRequireLicenseAcceptance&gt; 
    &lt;PackageReleaseNotes&gt;- Update README.md&lt;/PackageReleaseNotes&gt; 
    &lt;GeneratePackageOnBuild&gt;True&lt;/GeneratePackageOnBuild&gt; 
  &lt;PropertyGroup&gt; 
&lt;/Project&gt;</code></pre><p>The package identifier and the version number uniquely identify the exact code that's contained in the package. This is important to know. Once a package has been added to a NuGet source it cannot be modified anymore or replaced. Any changes to the source code or package properties require a new build and pack process. Hence, the package identifier and the version number uniquely identify the exact code that's contained in the package.</p><p>A list of all MSBuild properties is found in the reference section of the documentation: <a href="https://learn.microsoft.com/en-us/nuget/reference/msbuild-targets">NuGet pack and restore as MSBuild targets</a>.</p><p>After package creation you can still check and inspect the generated <code>.nupkg</code> file to see whether all intended content is present.</p><p>Note: <em>A NuGet package with the <code>.nupkg</code> extension is simply a ZIP file. To easily examine any package's contents, change the extension to <code>.zip</code> and expand its contents as usual. Just be sure to change the extension back to <code>.nupkg</code> before attempting to upload it to a host.</em></p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://jochen.kirstaetter.name/content/images/2024/02/image-12.png" class="kg-image" alt="Create NuGet packages with Visual Studio / Visual Studio Code"><figcaption>A <code>.nupkg</code> file is simply a ZIP archive. Here checking assets</figcaption></figure><p>This also allows you to quickly review the generated <code>.nuspec</code> file.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://jochen.kirstaetter.name/content/images/2024/02/image-13.png" class="kg-image" alt="Create NuGet packages with Visual Studio / Visual Studio Code"><figcaption>The package contains the assemblies for each targetted .NET version</figcaption></figure><p>You can check all assets needed per targetted .NET version.</p><h2 id="using-a-nuspec-file">Using a NuSpec file</h2><p>In case that the available MSBuild properties are not sufficient enough to define all package atrributes, it is still possible to add a <code>.nuspec</code> file to the project with more details.</p><p>Learn more about <a href="https://learn.microsoft.com/en-us/nuget/reference/msbuild-targets#packing-using-a-nuspec-file">packing using a <code>.nuspec</code> file</a>.</p><h2 id="deploy-a-nuget-package">Deploy a NuGet package</h2><p>After completing the <code>dotnet pack</code> command you can distribute the <code>.nupkg</code> file to a shared store or publish it to a NuGet source.</p><h3 id="use-a-network-drive">Use a network drive</h3><p>Because <code>pack</code> and <code>restore</code> are MSBuild targets, you can access them to enhance your workflow. For example, let's say you want to copy your package to a network share after packing it. You can do that by adding the following in your project file:</p><pre><code>&lt;Target Name="CopyPackage" AfterTargets="Pack"&gt; 
  &lt;Copy 
    SourceFiles="$(OutputPath)..\$(PackageId).$(PackageVersion).nupkg" 
    DestinationFolder="\\myshare\packageshare\" /&gt; 
&lt;/Target&gt;</code></pre><h3 id="azure-artifacts">Azure Artifacts</h3><p>Quite often there is a correlation between projects written in .NET and using Azure DevOps for continuous integration (CI) and continuous deployment (CD). One and more pipelines in Azure DevOps are used to create, pack, and deploy projects.</p><p>The resulting assemblies, or in this case, the NuGet package can then be pushed to Azure Artifacts and accessed by other developer that have access to that store.</p><p>Probably, it is an option to distribute NuGet packages among smaller teams of developers. More on this approach below.</p><h3 id="nuget-gallery">NuGet Gallery</h3><p>If you are comfortable publishing your package to the rest of the world then the NuGet Gallery might be your first choice to spread your codes. Setting up an account is straight forward and a matter of seconds using a Microsoft account. </p><p>Then upload the <code>.nupkg</code> file to the nuget.org web portal and you are officially published as a NuGet package maintainer.</p><p>Alternatively, you can push the package using a command line. To push packages to nuget.org with a command line, you can use either <code>dotnet.exe</code> or <code>nuget.exe</code> v4.1.0 or above, which implement the required NuGet protocols. </p><p>All the necessary steps are largely described in <a href="https://learn.microsoft.com/en-us/nuget/nuget-org/publish-a-package">Push NuGet packages</a> in the official documentation.</p><h3 id="third-party-systems">Third party systems</h3><p>There are other free and proprietary solutions to handle packages and source feeds within your organisation. In the past I used to work with the likes of ProGet and MyGet.</p><p>BTW, all that could be integrated into a CI/CD pipeline with minimal effort.</p><h2 id="summary">Summary</h2><p>Using NuGet packages whether in context of private, in-house development or public sets boundaries between different responsibilities, capabilities, and functionalities of an application. Furthermore, it allows that development can be done as independent units and provides more stability across multiple projects and therefore development teams. New versions of packages can be developed without having concerns to break existing projects by others that are incorporating that functionality. And with access to previous versions of a NuGet package software developers have peace of mind regarding their decision when to upgrade and more importantly that a rollback is possible anytime in case there might be breaking changes.</p><p>Access to pre-release versions of a NuGet package can easily be handled alongside the releases of stable versions.</p><!--kg-card-begin: html--><small>Image credit: Gemini using prompt "an image showing the creation of packages"</small><!--kg-card-end: html-->]]></content:encoded></item><item><title><![CDATA[Getting Started with the Vertex AI Gemini API with Visual Studio]]></title><description><![CDATA[Access to Vertex AI Gemini API is currently offered through SDKs not including C#. Visual Studio 2022 comes with an integrated HTTP client using .http files. The article shows how to access Vertex AI Gemini API using .http files.]]></description><link>https://jochen.kirstaetter.name/getting-started-with-the-vertex-ai-gemini-with-vs-http/</link><guid isPermaLink="false">65d84d44f2f01b106a4247e0</guid><category><![CDATA[Development]]></category><dc:creator><![CDATA[Jochen Kirstätter]]></dc:creator><pubDate>Fri, 23 Feb 2024 09:24:53 GMT</pubDate><media:content url="https://jochen.kirstaetter.name/content/images/2024/02/vertex-gemini-visualstudio.jpg" medium="image"/><content:encoded><![CDATA[<img src="https://jochen.kirstaetter.name/content/images/2024/02/vertex-gemini-visualstudio.jpg" alt="Getting Started with the Vertex AI Gemini API with Visual Studio"><p>Naming things in information technology is a hard nut to crack, and so it is not surprising that recent announcements about the line of Gemini products might be confusing. This article focuses on using the <a href="https://cloud.google.com/vertex-ai/docs/generative-ai/learn/overview">Vertex AI Gemini API</a> provided by Google Cloud Platform.</p><blockquote>Generative AI on Vertex AI (also known as <em>genAI</em> or <em>gen AI</em>) gives you access to Google's large generative AI models so you can test, tune, and deploy them for use in your AI-powered applications.</blockquote><p>It's the professional or enterprise offering compared to the consumer oriented AI Studio. Access to Vertex AI Gemini API is currently offered through SDKs for various programming languages like Python, Go, Node.js, and Java.</p><h2 id="set-up-vertex-ai">Set up Vertex AI</h2><p>First, you need an account on <a href="https://console.cloud.google.com/">Google Cloud</a>. If you don't already have one you can sign up and benefit from $US 300 credits to start with.</p><p>To use Vertex AI it is necessary to create or use an existing project, billing needs to be enabled for that project, and the Vertex AI API needs to be enabled.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://jochen.kirstaetter.name/content/images/2024/02/image-5.png" class="kg-image" alt="Getting Started with the Vertex AI Gemini API with Visual Studio" srcset="https://jochen.kirstaetter.name/content/images/size/w600/2024/02/image-5.png 600w, https://jochen.kirstaetter.name/content/images/2024/02/image-5.png 898w" sizes="(min-width: 720px) 720px"><figcaption>Enable the Vertex AI API in a project with billing</figcaption></figure><p>Then navigate to the Artificial Intelligence section, choose Vertex AI menu and open the Multimodal entry under Vertex AI Studio. This should be your launch base to prompts and the documentation, if necessary.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://jochen.kirstaetter.name/content/images/2024/02/image-6.png" class="kg-image" alt="Getting Started with the Vertex AI Gemini API with Visual Studio" srcset="https://jochen.kirstaetter.name/content/images/size/w600/2024/02/image-6.png 600w, https://jochen.kirstaetter.name/content/images/2024/02/image-6.png 608w"><figcaption>Accessing multimodal models in Vertex AI Studio</figcaption></figure><h3 id="gemini-api-offerings">Gemini API offerings</h3><p>The <a href="https://cloud.google.com/vertex-ai/docs/generative-ai/multimodal/overview">Vertex AI Gemini API</a> contains the publisher endpoints for the Gemini models developed by Google DeepMind.</p><ul><li><strong>Gemini 1.0 Pro</strong> is designed to handle natural language tasks, multiturn text and code chat, and code generation.</li><li><strong>Gemini 1.0 Pro Vision</strong> supports multimodal prompts. You can include text, images, and video in your prompt requests and get text or code responses.</li></ul><h2 id="set-up-visual-studio">Set up Visual Studio</h2><p>With the release of Visual Studio 2022 Version 17.5 there is a new feature available that allows for better, faster API development using <code>.http</code>/<code>.rest</code> files with an integrated HTTP client. Those files enable you to "run" your API endpoints and manipulate various REST calls to iterate within parameters and see the outputs in a structured way. Learn more about <a href="https://devblogs.microsoft.com/visualstudio/visual-studio-2022-17-5-released/#api">Visual Studio 2022 - 17.5 release announcement</a>.</p><p>Similar to the set up procedures for <a href="https://jochen.kirstaetter.name/getting-started-with-gemini-using-vs-http/">Getting started with Gemini using Visual Studio</a> create a project, probably a web application or API one and create an .http file to start with.</p><p>In order to keep private, sensitive information and secrets out of your source code repositories, it is recommended to use either Environment Variables, User Secrets, or Azure Key Vault to retrieve data like the project ID or an access token. Here, I'm going to create an <code>.env</code> file and place it into the project folder with the following content.</p><pre><code>PROJECT_ID=&lt;your Google Cloud project ID&gt;
ACCESS_TOKEN=&lt;your access token to Google Cloud&gt;</code></pre><p>To access the value of a variable that is defined in a <code>.env</code> file, use <code>$dotenv</code>. More details are described under <a href="https://learn.microsoft.com/en-us/aspnet/core/test/http-files?view=aspnetcore-8.0#environment-variables">Environment Variables</a>  in the official documentation.</p><p>After you logged into Google Cloud either using the Console Shell or the <code>gcloud</code> CLI tool (recommended) you can retrieve the access token with the following command.</p><pre><code>$ gcloud auth print-access-token</code></pre><p>Copy and paste the output as value of the <code>ACCESS_TOKEN</code> variable into your <code>.env</code> file. In case that the next request is still not authorized, make a small change to the <code>.http</code> fle content and try again. There seems to be a slight delay or synchronisation issue in the integrated REST client.</p><h2 id="use-the-vertex-ai-gemini-api">Use the Vertex AI Gemini API</h2><p>The documentation on Google Cloud describes the <a href="https://cloud.google.com/vertex-ai/docs/generative-ai/model-reference/overview">Generative AI foundational model reference</a> in general, and its <a href="https://cloud.google.com/vertex-ai/docs/generative-ai/model-reference/gemini">Gemini API</a> in particular. Here, there are two API endpoints of interest.</p><pre><code>https://{REGION}-aiplatform.googleapis.com/v1/projects/{PROJECT_ID}/locations/{REGION}/publishers/google/models/gemini-1.0-pro:streamGenerateContent

https://{REGION}-aiplatform.googleapis.com/v1/projects/{PROJECT_ID}/locations/{REGION}/publishers/google/models/gemini-1.0-pro-vision:streamGenerateContent</code></pre><p>The difference between both is simply the selection of model - <code>gemini-1.0-pro</code> and <code>gemini-1.0-pro-vision</code>. There is the method <code>streamGenerateContent</code> only to generate information based on the data and prompts you send to the API.</p><h2 id="use-the-gemini-1-0-pro-model">Use the Gemini 1.0 Pro model</h2><p>The Gemini 1.0 Pro (<code>gemini-1.0-pro</code>) model is tailored for natural language tasks such as classification, summarization, extraction, and writing.</p><h3 id="generate-text-from-text">Generate text from text</h3><p>Send a text prompt to the model. The Gemini 1.0 Pro (<code>gemini-1.0-pro</code>) model provides a streaming response mechanism: <code>streamGenerateContent</code>. With this approach, you don't need to wait for the complete response; you can start processing fragments as soon as they're accessible.</p><pre><code>@projectId={{$dotenv PROJECT_ID}}
@accessToken={{$dotenv ACCESS_TOKEN}}
@region=us-central1
@model=gemini-1.0-pro
@apiEndpoint={{region}}-aiplatform.googleapis.com

# Send a text-only request
POST https://{{apiEndpoint}}/v1/projects/{{projectId}}/locations/{{region}}/publishers/google/models/{{model}}:streamGenerateContent
Authorization: Bearer {{accessToken}}
Content-Type: application/json

{
  "contents": {
    "role": "USER",
    "parts": { "text": "Why is the sky blue?" }
  }
}</code></pre><h3 id="working-with-configuration-parameters">Working with configuration parameters</h3><p>Every prompt you send to the model includes parameter values that control how the model generates a response. The model can generate different results for different parameter values. Learn more about <a href="https://ai.google.dev/docs/concepts#model_parameters">model parameters</a>.</p><p>Also, you can use safety settings to adjust the likelihood of getting responses that may be considered harmful. By default, safety settings block content with medium and/or high probability of being unsafe content across all dimensions. Learn more about <a href="https://ai.google.dev/docs/concepts#safety_setting">safety settings</a>.</p><pre><code>@projectId={{$dotenv PROJECT_ID}}
@accessToken={{$dotenv ACCESS_TOKEN}}
@region=us-central1
@model=gemini-1.0-pro
@apiEndpoint={{region}}-aiplatform.googleapis.com

# Send a text-only request with model parameters and safety settings
POST https://{{apiEndpoint}}/v1/projects/{{projectId}}/locations/{{region}}/publishers/google/models/{{model}}:streamGenerateContent
Authorization: Bearer {{accessToken}}
Content-Type: application/json

{
  "contents": {
    "role": "USER",
    "parts": { "text": "Why is the sky blue?" }
  },
  "generation_config": {
    "temperature": 0.2,
    "top_p": 0.1,
    "top_k": 16,
    "max_output_tokens": 2048,
    "candidate_count": 1,
    "stop_sequences": []
  },
  "safety_settings": {
    "category": "HARM_CATEGORY_SEXUALLY_EXPLICIT",
    "threshold": "BLOCK_LOW_AND_ABOVE"
  }
}</code></pre><h3 id="multi-turn-conversations-chat-">Multi-turn conversations (chat)</h3><p>The Gemini 1.0 Pro model supports natural multi-turn conversations and is ideal for text tasks that require back-and-forth interactions. Specify the <code>role</code> field only if the content represents a turn in a conversation. You can set <code>role</code> to one of the following values: <code>user</code>, <code>model</code>.</p><pre><code>@projectId={{$dotenv PROJECT_ID}}
@accessToken={{$dotenv ACCESS_TOKEN}}
@region=us-central1
@model=gemini-1.0-pro
@apiEndpoint={{region}}-aiplatform.googleapis.com

# Using multi-turn conversations (chat)
POST https://{{apiEndpoint}}/v1/projects/{{projectId}}/locations/{{region}}/publishers/google/models/{{model}}:streamGenerateContent
Authorization: Bearer {{accessToken}}
Content-Type: application/json

{
  "contents": [
    {
      "role": "user",
      "parts": [
        { "text": "Hello" }
      ]
    },
    {
      "role": "model",
      "parts": [
        { "text": "Hello! I am glad you could both make it." }
      ]
    },
    {
      "role": "user",
      "parts": [
        { "text": "So what is the first order of business?" }
      ]
    }
  ]
}</code></pre><blockquote>The first order of business is to introduce ourselves and get to know each other.</blockquote><h2 id="use-the-gemini-1-0-pro-vision-model">Use the Gemini 1.0 Pro Vision model</h2><p>The Gemini 1.0 Pro Vision (<code>gemini-1.0-pro-vision</code>) is a multimodal model that supports adding image and video in text or chat prompts for a text response.</p><p><strong>Note</strong>: <em>Text-only prompts are not supported by the Gemini 1.0 Pro Vision model. Instead, use the Gemini 1.0 Pro model for text-only prompts.</em></p><h3 id="generate-text-from-a-local-image">Generate text from a local image</h3><p>Specify the <a href="https://en.wikipedia.org/wiki/Base64">base64</a> encoding of the image or video to include inline in the prompt and the <code>mime_type</code> field. The supported <a href="https://en.wikipedia.org/wiki/Media_type">MIME types</a> for images include <code>image/png</code> and <code>image/jpeg</code>.</p><pre><code>@projectId={{$dotenv PROJECT_ID}}
@accessToken={{$dotenv ACCESS_TOKEN}}
@region=us-central1
@model=gemini-1.0-pro-vision
@apiEndpoint={{region}}-aiplatform.googleapis.com

# Generate text from a local image. 
# Command Prompt base64 conversion used: certutil -encodehex -f "scones.jpg" "output.txt" 0x40000001 1&gt;nul
POST https://{{apiEndpoint}}/v1/projects/{{projectId}}/locations/{{region}}/publishers/google/models/{{model}}:streamGenerateContent
Authorization: Bearer {{accessToken}}
Content-Type: application/json

{
  "contents": {
    "role": "USER",
    "parts": [
      {
        "text": "What is this picture?"
      },
      {
        "inline_data": {
          "mime_type":"image/jpeg",
          "data": "/9j/4AAQSkZJRgA...Wup/9k="
        }
      }
    ]
  }
}</code></pre><p>Here's the excerpt from the streamed response.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://jochen.kirstaetter.name/content/images/2024/02/image-7.png" class="kg-image" alt="Getting Started with the Vertex AI Gemini API with Visual Studio" srcset="https://jochen.kirstaetter.name/content/images/size/w600/2024/02/image-7.png 600w, https://jochen.kirstaetter.name/content/images/2024/02/image-7.png 714w"><figcaption>Response from Vertex AI using Gemini API</figcaption></figure><blockquote>The picture shows a table with a cup of coffee, a bowl of blueberries, and several blueberry scones. There are also pink flowers on the table.</blockquote><p>Here are the steps to get the sample image and encode it in base64. The image is available here. It has been resized to a width of 512px prior to base64 encoding.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://jochen.kirstaetter.name/content/images/2024/02/scones.jpg" class="kg-image" alt="Getting Started with the Vertex AI Gemini API with Visual Studio"><figcaption>Image used as part of multimodal prompt using gemini-pro-vision model</figcaption></figure><pre><code class="language-bsh">https://storage.googleapis.com/generativeai-downloads/images/scones.jpg</code></pre><p>On Windows use a Command Prompt with the <code>certutil</code> command.</p><pre><code>&gt; certutil -encodehex -f "scones.jpg" "output.txt" 0x40000001 1&gt;nul</code></pre><p>Whereas on Linux or macOS use the <code>base64</code> command to encode the image.</p><pre><code>$ base64 -w0 scones.jpg &gt; output.txt</code></pre><p>Note: <em>At the time of writing .http/.rest files in Visual Studio 2022 do not provide a functionality to read external files directly.</em></p><h3 id="generate-text-from-an-image-on-google-cloud-storage">Generate text from an image on Google Cloud Storage</h3><p>Specify the Cloud Storage URI of the image to include in the prompt. The bucket that stores the file must be in the same Google Cloud project that's sending the request. You must also specify the <code>mime_type</code> field. The supported image MIME types include <code>image/png</code> and <code>image/jpeg</code>.</p><figure class="kg-card kg-image-card"><img src="https://jochen.kirstaetter.name/content/images/2024/02/cat.jpg" class="kg-image" alt="Getting Started with the Vertex AI Gemini API with Visual Studio"></figure><pre><code>@projectId={{$dotenv PROJECT_ID}}
@accessToken={{$dotenv ACCESS_TOKEN}}
@region=us-central1
@model=gemini-1.0-pro
@apiEndpoint={{region}}-aiplatform.googleapis.com

# Generate text from an image on Google Cloud Storage.
POST https://{{apiEndpoint}}/v1/projects/{{projectId}}/locations/{{region}}/publishers/google/models/{{model}}:streamGenerateContent
Authorization: Bearer {{accessToken}}
Content-Type: application/json

{
  "contents": {
    "role": "USER",
    "parts": [
      {"text": "Is it a cat?"},
      {"file_data": {
        "mime_type": "image/jpeg",
        "file_uri": "gs://cloud-samples-data/generative-ai/image/320px-Felis_catus-cat_on_snow.jpg"
      }}
    ]
  }
}</code></pre><blockquote>A cat with gray and black stripes is walking in the snow.</blockquote><h3 id="generate-text-from-a-video-file">Generate text from a video file</h3><p>Specify the Cloud Storage URI of the video to include in the prompt. The bucket that stores the file must be in the same Google Cloud project that's sending the request. You must also specify the <code>mime_type</code> field. The supported MIME types for video include <code>video/mp4</code>.</p><pre><code>@projectId={{$dotenv PROJECT_ID}}
@accessToken={{$dotenv ACCESS_TOKEN}}
@region=us-central1
@model=gemini-1.0-pro
@apiEndpoint={{region}}-aiplatform.googleapis.com

# Generate text from a video file.
# Using Google Storage as a source.
POST https://{{apiEndpoint}}/v1/projects/{{projectId}}/locations/{{region}}/publishers/google/models/{{model}}:streamGenerateContent
Authorization: Bearer {{accessToken}}
Content-Type: application/json

{
  "contents": {
    "role": "USER",
    "parts": [
      {
        "text": "Answer the following questions using the video only. What is the profession of the main person? What are the main features of the phone highlighted?Which city was this recorded in?Provide the answer JSON."
      },
      {
        "file_data": {
          "mime_type": "video/mp4",
          "file_uri": "gs://github-repo/img/gemini/multimodality_usecases_overview/pixel8.mp4"
        }
      }
    ]
  }
}</code></pre><h2 id="limited-to-visual-studio">Limited to Visual Studio?</h2><p>Absolutely not!</p><p>I successfully used the same set of .http files in the following text editors and environments with the REST Client extension by Huachao Mao.</p><ul><li>Visual Studio Code - locally and online <a href="https://vscode.dev/">https://vscode.dev/</a></li><li>Google Cloud Shell Editor (Code OSS for the Web)</li><li>Project IDX - <a href="https://idx.dev/">https://idx.dev/</a></li></ul><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://jochen.kirstaetter.name/content/images/2024/02/image-2.png" class="kg-image" alt="Getting Started with the Vertex AI Gemini API with Visual Studio"><figcaption>Using REST Client extension in Code to prompt Vertex AI Gemini API</figcaption></figure><figure class="kg-card kg-image-card"><img src="https://jochen.kirstaetter.name/content/images/2024/02/image-3.png" class="kg-image" alt="Getting Started with the Vertex AI Gemini API with Visual Studio"></figure><h2 id="source-code-gemini-playground">Source code: Gemini Playground</h2><p>I created a repository on GitHub <a href="https://github.com/mscraftsman/gemini-playground">gemini-playground</a> that contains all samples described above with the exception of the <code>.env</code> file and the credentials to access the Vertex AI Gemini API. Feel free to give it a star and fork it for your own purpose.</p><h2 id="migrate-from-gemini-on-google-ai-to-vertex-ai">Migrate from Gemini on Google AI to Vertex AI</h2><p>As mentioned initially there are multiple "Gemini AI" offerings available. If you are new to Gemini, using the <a href="https://ai.google.dev/tutorials/python_quickstart">quickstarts</a> and <a href="https://ai.google.dev/pricing">plans</a> for <a href="https://ai.google.dev/tutorials/ai-studio_quickstart">Google AI Studio</a> is the fastest way to get started.</p><p>However, as your generative AI solutions mature, you may need a platform for building and deploying generative AI applications and solutions end to end. Google Cloud provides a comprehensive ecosystem of tools to enable developers to harness the power of generative AI, from the initial stages of app deployment to managing complex data at scale. <a href="https://console.cloud.google.com/vertex-ai/generative">Google Cloud's Vertex AI platform</a> offers a suite of MLOps tools that streamline the usage, deployment, and monitoring of AI models for efficiency and reliability.</p><p>Learn more about Gemini API and the <a href="https://cloud.google.com/vertex-ai/docs/generative-ai/migrate/migrate-google-ai">Google AI versus Vertex AI differences</a>.</p><h2 id="lastly-why-is-the-sky-blue">Lastly, why is the sky blue?</h2><p>Here's the response I was provided by Vertex AI Gemini API.</p><blockquote>The sky is blue due to a phenomenon called Rayleigh scattering. This scattering occurs because the shorter wavelengths of sunlight (blue and violet) are scattered more effectively by molecules in the atmosphere than longer wavelengths (red and orange). The scattered blue light is what we see when we look up at the sky, while the longer wavelengths of light pass through the atmosphere and reach our eyes as sunlight.</blockquote>]]></content:encoded></item><item><title><![CDATA[Getting started with Gemini using Visual Studio]]></title><description><![CDATA[Visual Studio 2022 comes with an integrated HTTP client using .http files. The article shows how to access Gemini AI using .http files. Which also works in VS Code using REST Client extension.]]></description><link>https://jochen.kirstaetter.name/getting-started-with-gemini-using-vs-http/</link><guid isPermaLink="false">65d705d3f2f01b106a4245b4</guid><category><![CDATA[Development]]></category><dc:creator><![CDATA[Jochen Kirstätter]]></dc:creator><pubDate>Thu, 22 Feb 2024 12:56:58 GMT</pubDate><media:content url="https://jochen.kirstaetter.name/content/images/2024/02/gemini-visualstudio.jpg" medium="image"/><content:encoded><![CDATA[<img src="https://jochen.kirstaetter.name/content/images/2024/02/gemini-visualstudio.jpg" alt="Getting started with Gemini using Visual Studio"><p>With the release of Visual Studio 2022 Version 17.5 there is a new feature available that allows for better, faster API development using <code>.http</code>/<code>.rest</code> files with an integrated HTTP client. Those files enable you to "run" your API endpoints and manipulate various REST calls to iterate within parameters and see the outputs in a structured way.</p><p>Access to Gemini is currently offered through SDKs for various programming languages like Python, Go, Node.js, and so forth, including the barebone REST API. You can get an overview here: <a href="https://ai.google.dev/tutorials">https://ai.google.dev/tutorials</a> </p><p>The tutorial on <a href="https://ai.google.dev/tutorials/rest_quickstart">Quickstart: Get started with Gemini using the REST API</a> is limited to the use of the <code>curl</code> command only.</p><blockquote>If you want to quickly try out the Gemini API, you can use <code>curl</code> commands to call the methods in the REST API. The examples in this tutorial show calls for each API method.</blockquote><p>As a Windows developer using Visual Studio this might not be the optimum starting point, hence this article which calls the same REST API using .http/.rest files in Visual Studio.</p><blockquote>These .http/.rest files aren’t meant to replace integration and unit testing. Instead, they provide a new way to rapidly iterate on API development, as well as a common place to monitor the APIs your app may be using and investigate required inputs/outputs during development.</blockquote><p>Learn more about <a href="https://devblogs.microsoft.com/visualstudio/visual-studio-2022-17-5-released/#api">Visual Studio 2022 - 17.5 release announcement</a>.</p><h3 id="set-up-your-api-key">Set up your API key</h3><p>To use the Gemini API, you'll need an API key. If you don't already have one, create a key in <a href="https://aistudio.google.com/app/apikey">Google AI Studio</a>.</p><!--kg-card-begin: html--><a class="button button-primary" href="https://aistudio.google.com/app/apikey" target="_blank" rel="noopener noreferrer">Get an API key</a>
<!--kg-card-end: html--><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://jochen.kirstaetter.name/content/images/2024/02/Screenshot-from-2024-02-22-13-47-53.png" class="kg-image" alt="Getting started with Gemini using Visual Studio" srcset="https://jochen.kirstaetter.name/content/images/size/w600/2024/02/Screenshot-from-2024-02-22-13-47-53.png 600w, https://jochen.kirstaetter.name/content/images/2024/02/Screenshot-from-2024-02-22-13-47-53.png 769w" sizes="(min-width: 720px) 720px"><figcaption>Create an API key to access Gemini REST API</figcaption></figure><p>In order to keep private, sensitive information and secrets out of your source code repositories, it is recommended to use either Environment Variables, User Secrets, or Azure Key Vault to retrieve data like an API key. Here, I'm going to create an <code>.env</code> file and place it into the project folder with the following content.</p><pre><code>API_KEY=&lt;The generated Gemini API key&gt;</code></pre><p>To access the value of a variable that is defined in a <code>.env</code> file, use <code>$dotenv</code>. More details are described under <a href="https://learn.microsoft.com/en-us/aspnet/core/test/http-files?view=aspnetcore-8.0#environment-variables">Environment Variables</a>  in the official documentation.</p><p>All examples read the API key as environment variable from the <code>.env</code> file and stores it as a (local) variable. Additionally, there are variables for the API <code>version</code> and the <code>model</code> to be used. More information on <a href="https://ai.google.dev/docs/api_versions">API versions explained</a> in the official documentation.</p><h2 id="model-info">Model info</h2><p>When starting with the Gemini API there is often the question of <code>What's available?</code> Apart from the <a href="https://ai.google.dev/tutorials/rest_quickstart">documentation</a> you can query the Gemini API to retrieve a list of available models, and you can get the details of an individual model.</p><h3 id="list-models">List models</h3><p>If you <code>GET</code> the <code>models</code> directory, it uses the <code>list</code> method to list all of the models available through the API, including both the Gemini and PaLM family models.</p><pre><code>@apiKey={{$dotenv API_KEY}}
@version=v1beta

# Get a list of available models and description
GET https://generativelanguage.googleapis.com/{{version}}/models?key={{apiKey}}</code></pre><h3 id="get-model">Get model</h3><p>If you <code>GET</code> a model's URL, the API uses the <code>get</code> method to return information about that model such as version, display name, input token limit, etc.</p><figure class="kg-card kg-code-card"><pre><code>@apiKey={{$dotenv API_KEY}}
@version=v1beta
@model=gemini-pro

# Get information about the model, including default values
GET https://generativelanguage.googleapis.com/{{version}}/models/{{model}}?key={{apiKey}}</code></pre><figcaption>Get model details from Gemini API</figcaption></figure><p>The response might look like this.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://jochen.kirstaetter.name/content/images/2024/02/image.png" class="kg-image" alt="Getting started with Gemini using Visual Studio" srcset="https://jochen.kirstaetter.name/content/images/size/w600/2024/02/image.png 600w, https://jochen.kirstaetter.name/content/images/2024/02/image.png 752w" sizes="(min-width: 720px) 720px"><figcaption>Details and default values of gemini-pro model</figcaption></figure><h2 id="gemini-and-content-based-apis">Gemini and Content based APIs</h2><h3 id="text-only-input-gemini-pro-">Text-only input (Gemini Pro)</h3><p>For text-only input use the <code>gemini-pro</code> model and call the <code>generateContent</code> method to generate a response from the model. Using the variable values a <code>POST</code> request is send to the Gemini API endpoint with the prompt specified in JSON format.</p><figure class="kg-card kg-code-card"><pre><code>@apiKey={{$dotenv API_KEY}}
@version=v1beta
@model=gemini-pro

# Send a text-only request
POST https://generativelanguage.googleapis.com/{{version}}/models/{{model}}:generateContent?key={{apiKey}}
Content-Type: application/json

{
  "contents": [{
    "parts": [{
      "text": "Write a story about a magic backpack."
    }]
  }]
}</code></pre><figcaption>Calling the text-only API using gemini-pro model</figcaption></figure><h3 id="text-and-image-input-gemini-pro-vision-">Text-and-image input (Gemini Pro Vision)</h3><p>If the input contains both text and image, use the <code>gemini-pro-vision</code> model. The following snippets help you build a request and send it to the REST API.</p><figure class="kg-card kg-code-card"><pre><code>@apiKey={{$dotenv API_KEY}}
@version=v1beta
@model=gemini-pro-vision

# Send a text and image as input request. 
# Command Prompt base64 conversion used: certutil -encodehex -f "scones.jpg" "output.txt" 0x40000001 1&gt;nul
POST https://generativelanguage.googleapis.com/{{version}}/models/{{model}}:generateContent?key={{apiKey}}
Content-Type: application/json

{
  "contents":[
    {
      "parts":[
        {
          "text": "What is this picture?"
        },
        {
          "inline_data": {
            "mime_type":"image/jpeg",
            "data": "/9j/4AAQSkZ...GTWup/9k="
          }
        }
      ]
    }
  ]
}</code></pre><figcaption>Multimodal prompt with image analysis using gemini-pro-vision model</figcaption></figure><p>The various elements of your input are defined as <code>parts</code> in your prompt. Like previously, the <code>text</code> part contains your actual prompt and an additional file like an image is added as base64-encoded inline data including its mime type. The <code>data</code> key has a base64 encoded representation of the image to inspect using the prompt.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://jochen.kirstaetter.name/content/images/2024/02/image-4.png" class="kg-image" alt="Getting started with Gemini using Visual Studio" srcset="https://jochen.kirstaetter.name/content/images/size/w600/2024/02/image-4.png 600w, https://jochen.kirstaetter.name/content/images/2024/02/image-4.png 728w" sizes="(min-width: 720px) 720px"><figcaption>Response from Gemini AI</figcaption></figure><blockquote>The picture shows a table with a white tablecloth. On the table are two cups of coffee, two small bowls, one filled with blueberries and the other with a silver spoon. There are also three scones with blueberries on the table. Next to the scones are some peony flowers.</blockquote><p>Here are the steps to get the sample image and encode it in base64. The image is available here. It has been resized to a width of 512px prior to base64 encoding. </p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://jochen.kirstaetter.name/content/images/2024/02/scones.jpg" class="kg-image" alt="Getting started with Gemini using Visual Studio" srcset="https://jochen.kirstaetter.name/content/images/size/w600/2024/02/scones.jpg 600w, https://jochen.kirstaetter.name/content/images/size/w1000/2024/02/scones.jpg 1000w, https://jochen.kirstaetter.name/content/images/2024/02/scones.jpg 1280w" sizes="(min-width: 720px) 720px"><figcaption>Image used as part of multimodal prompt using gemini-pro-vision model</figcaption></figure><pre><code class="language-bsh">https://storage.googleapis.com/generativeai-downloads/images/scones.jpg</code></pre><p>On Windows use a Command Prompt with the <code>certutil</code> command.</p><pre><code>&gt; certutil -encodehex -f "scones.jpg" "output.txt" 0x40000001 1&gt;nul</code></pre><p>Whereas on Linux or macOS use the <code>base64</code> command to encode the image.</p><pre><code>$ base64 -w0 scones.jpg &gt; output.txt</code></pre><p>Note: <em>At the time of writing .http/.rest files in Visual Studio 2022 do not provide a functionality to read external files directly.</em></p><h3 id="count-tokens">Count tokens</h3><p>When using long prompts, it might be useful to count tokens before sending any content to the model.</p><pre><code>@apiKey={{$dotenv API_KEY}}
@version=v1beta
@model=gemini-pro

# Count tokens for a long prompt
POST https://generativelanguage.googleapis.com/{{version}}/models/{{model}}:countTokens?key={{apiKey}}
Content-Type: application/json

{
  "contents": [{
    "parts": [{
      "text": "Write an extended story about a magic backpack."
    }]
  }]
}</code></pre><h3 id="multi-turn-conversations-chat-">Multi-turn conversations (chat)</h3><p>Using Gemini, you can build freeform conversations across multiple turns.</p><pre><code>@apiKey={{$dotenv API_KEY}}
@version=v1beta
@model=gemini-pro

# Using multi-turn conversations (chat)
POST https://generativelanguage.googleapis.com/{{version}}/models/{{model}}:generateContent?key={{apiKey}}
Content-Type: application/json

{
  "contents": [
    {"role": "user",
      "parts": [{
        "text": "Write the first line of a story about a magic backpack."}]},
    {"role": "model",
      "parts": [{
        "text": "In the bustling city of Meadow brook, lived a young girl named Sophie. She was a bright and curious soul with an imaginative mind."}]},
    {"role": "user",
      "parts": [{
        "text": "Can you set it in a quiet village in 1600s France?"}]},
  ]
}</code></pre><h3 id="working-with-configuration-parameters">Working with configuration parameters</h3><p>Every prompt you send to the model includes parameter values that control how the model generates a response. The model can generate different results for different parameter values. Learn more about <a href="https://ai.google.dev/docs/concepts#model_parameters">model parameters</a>.</p><p>Also, you can use safety settings to adjust the likelihood of getting responses that may be considered harmful. By default, safety settings block content with medium and/or high probability of being unsafe content across all dimensions. Learn more about <a href="https://ai.google.dev/docs/concepts#safety_setting">safety settings</a>.</p><p>The following example specifies values for all the parameters of the <code>generateContent</code> method.</p><pre><code>@apiKey={{$dotenv API_KEY}}
@version=v1beta
@model=gemini-pro

# Send a text-only request with model parameters and safety settings
# Ref: https://ai.google.dev/docs/concepts#model-parameters
POST https://generativelanguage.googleapis.com/{{version}}/models/{{model}}:generateContent?key={{apiKey}}
Content-Type: application/json

{
  "contents": [{
    "parts": [{
      "text": "Write a story about a magic backpack."
    }]
  }],
  "safetySettings": [
    {
        "category": "HARM_CATEGORY_DANGEROUS_CONTENT",
        "threshold": "BLOCK_ONLY_HIGH"
    }
  ],
  "generationConfig": {
    "stopSequences": [
        "Title"
    ],
    "temperature": 1.0,
    "maxOutputTokens": 800,
    "topP": 0.8,
    "topK": 10
  }
}</code></pre><h2 id="limited-to-visual-studio">Limited to Visual Studio?</h2><p>Absolutely not! </p><p>I successfully used the same set of .http files in the following text editors and environments with the REST Client extension by Huachao Mao.</p><ul><li>Visual Studio Code - locally and online <a href="https://vscode.dev/">https://vscode.dev/</a></li><li>Google Cloud Shell Editor (Code OSS for the Web)</li><li>Project IDX - <a href="https://idx.dev/">https://idx.dev/</a></li></ul><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://jochen.kirstaetter.name/content/images/2024/02/image-2.png" class="kg-image" alt="Getting started with Gemini using Visual Studio" srcset="https://jochen.kirstaetter.name/content/images/size/w600/2024/02/image-2.png 600w, https://jochen.kirstaetter.name/content/images/size/w1000/2024/02/image-2.png 1000w, https://jochen.kirstaetter.name/content/images/2024/02/image-2.png 1213w" sizes="(min-width: 720px) 720px"><figcaption>Using REST Client extension in Code to prompt Gemini API</figcaption></figure><figure class="kg-card kg-image-card"><img src="https://jochen.kirstaetter.name/content/images/2024/02/image-3.png" class="kg-image" alt="Getting started with Gemini using Visual Studio" srcset="https://jochen.kirstaetter.name/content/images/size/w600/2024/02/image-3.png 600w, https://jochen.kirstaetter.name/content/images/size/w1000/2024/02/image-3.png 1000w, https://jochen.kirstaetter.name/content/images/size/w1600/2024/02/image-3.png 1600w, https://jochen.kirstaetter.name/content/images/size/w2400/2024/02/image-3.png 2400w" sizes="(min-width: 720px) 720px"></figure><h2 id="source-code-gemini-playground">Source code: Gemini Playground</h2><p>I created a repository on GitHub <a href="https://github.com/mscraftsman/gemini-playground">gemini-playground</a> that contains all samples described above with the exception of the <code>.env</code> file and the API key to access the Gemini REST API. Feel free to give it a star and fork it for your own purpose.</p><h2 id="georestricted-access-to-api-of-gemini-ai">Georestricted access to API of Gemini AI</h2><p>Unfortunately, if you are residing in a country that has no access to the API  endpoints of Gemini AI you will get an HTTP 400 response like the following one.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://jochen.kirstaetter.name/content/images/2024/02/image-1.png" class="kg-image" alt="Getting started with Gemini using Visual Studio" srcset="https://jochen.kirstaetter.name/content/images/size/w600/2024/02/image-1.png 600w, https://jochen.kirstaetter.name/content/images/2024/02/image-1.png 743w" sizes="(min-width: 720px) 720px"><figcaption>Access to Gemini API is still restricted in some countries</figcaption></figure><h2 id="lastly-a-story-about-a-magic-backpack">Lastly, a story about a magic backpack</h2><p>Here's the response I was provided by Gemini API.</p><p><em>Once upon a time, in a bustling town by the forest's edge, lived a young boy named Alex. Alex was an inquisitive and adventurous child who loved exploring the woods and playing with his friends. However, he had a secret desire that no one knew about—he craved magic and adventure.</em></p><p><em>One morning, as Alex wandered through the forest on his way to school, he stumbled upon a hidden glade. Fascinated by the serene atmosphere, he ventured deeper, following a trail of glowing fireflies. In the heart of the glade, beneath an ancient oak tree, lay a worn-out backpack. Curiosity compelling him, Alex reached out and touched it.</em></p><p><em>As soon as his fingers brushed against the bag, it sprung to life. The backpack shimmered with brilliant colors, its straps adjusting perfectly to Alex's shoulders as if it was made just for him. With a growing sense of excitement, Alex opened the bag's main compartment and discovered a swirling vortex of colors.</em></p><p><em>The vortex seemed to call to Alex, inviting him to step inside. Hesitating for a moment, he realized this was the magic and adventure he had always yearned for. With newfound courage, he took a deep breath and stepped through the portal, disappearing into the vibrant void.</em></p><p><em>The world inside the backpack was nothing like Alex had ever imagined. It was an expansive realm filled with floating islands, luminous waterfalls, and ethereal creatures. Every corner held a new discovery, from talking animals to enchanted artifacts.</em></p><p><em>Alex spent countless hours exploring this magical realm, making friends with the creatures and unraveling its mysteries. He learned the art of flying, telekinesis, and even conjuring illusions. Along his journey, he met a wise old wizard who became his mentor, teaching him valuable lessons about magic and responsibility.</em></p><p><em>As Alex grew wiser and more skilled, he realized that the backpack's magic was not without its consequences. With every spell he cast, a faint shimmer of darkness would appear on the bag's surface. He soon understood that the backpack had a life of its own, and its power could be both a blessing and a curse.</em></p><p><em>Determined to make the most of his time in the magical realm, Alex embarked on a quest to find the legendary "Heart of Magic," an artifact said to hold the power to restore balance and harmony to the backpack's magic. Along the way, he faced challenges, encountered dangerous creatures, and forged alliances with unlikely companions.</em></p><p><em>When Alex finally found the Heart of Magic, he was given the choice to either return home to his old life or remain in the magical realm forever. With a heavy heart, he made the difficult decision to say goodbye to his friends and the world he had come to love.</em></p><p><em>Stepping back through the vortex in the backpack, Alex found himself back in the forest glade, the backpack now nothing more than an ordinary worn-out bag. He carried it with him, cherishing the memories of his magical journey, knowing that he had grown and learned valuable lessons about friendship, magic, and the choices that shape one's destiny.</em></p>]]></content:encoded></item><item><title><![CDATA[Developer Creators and Online Communities Summit]]></title><description><![CDATA[The Google Developer Community organised the first Developer Creators and Online Communities Summit in Singapore. I had the honour to join approx. 120 people and learn a lot over there.]]></description><link>https://jochen.kirstaetter.name/developer-creators-and-online-communities-summit/</link><guid isPermaLink="false">65af3347f2f01b106a4236cd</guid><category><![CDATA[Community]]></category><dc:creator><![CDATA[Jochen Kirstätter]]></dc:creator><pubDate>Thu, 01 Feb 2024 10:13:34 GMT</pubDate><media:content url="https://jochen.kirstaetter.name/content/images/2024/01/PXL_20240125_094817421.MP.jpg" medium="image"/><content:encoded><![CDATA[<img src="https://jochen.kirstaetter.name/content/images/2024/01/PXL_20240125_094817421.MP.jpg" alt="Developer Creators and Online Communities Summit"><p>New year, new activities. It's still January and I'm already on tour. I was heading to the <a href="https://rsvp.withgoogle.com/events/developer-creators-and-online-communities-summit">Developer Creators and Online Communities Summit</a> - <a href="https://twitter.com/hashtag/GoogleDCOC?src=hashtag_click">#GoogleDCOC</a> - in Singapore. It's a global hybrid event - meaning in-person and online. The purpose is to bring together content creators and online community managers in the developer space from all around the world.</p><h2 id="why-attending-in-person">Why attending in-person?</h2><p>I'm excited about this summit for various reasons. First and foremost, apart from blogging since over a decade I'm diving more and more into other ways of content creation. Already back in 2020, we recorded the whole <a href="https://jochen.kirstaetter.name/how-did-we-run-the-virtual-developers-conference-2020/">Virtual Developers Conference in Mauritius</a> - 4 tracks over 3 days, more than 100 hours of technical presentations - then post-processed everything and re-published every single session on its own. <a href="https://www.youtube.com/c/MauritiusSoftwareCraftsmanshipCommunity">Everything available on YouTube</a>. That conference alone has <a href="https://www.youtube.com/playlist?list=PLjTJ1efie4x_lZ_fI1m4I1EHauG40pBUo">over 90 videos in its playlist</a>.</p><p>Additionally, I started recording talks happening during our monthly <a href="https://www.mscc.mu/">MSCC</a> meetings. Most of them still need processing but are coming to the YouTube channel soon. Pinky promise!</p><p>And not to forget: <em>Podcasts</em>!‌‌</p><p>Although the concept and "launch" of the <a href="https://podcast.mscc.mu/">Talks on Software Craftsmanship</a> has been around since 2020 as announced at the end of the Virtual Developers Conference it didn't take off yet. Unfortunately, for various reasons which are mainly down to the procrastination of the host(s). Which is another pinky promise: Reviving, eh really launching, this podcast.</p><p>And what's a good motivator for that? Yes, you're right, podcasting. So, recently my friend and long-time community supporter Loic Forget took the lead in realising the podcast "<a href="https://open.spotify.com/show/0fFAunlT6yaidBjLHSN5F2">Mau Pas Konpran!?</a>" (published on Open Spotify). Together with <a href="https://sysadmin-journal.com/">Ish Sookun</a> we are sitting together for a semi-technical, monthly recording session. The fun part here is that each episode is held in typical Mauritian style. We are conversing about local topics in at least three languages - Kreol Morisien, English, and a little bit of French or German. For me, that's a great learning experience on multiple levels.</p><p>Attending the summit I was highly interested in networking with other creators and to learn from their experiences. Which equipment to consider and which software applications are recommended for processing. Tips &amp; tricks publishing on YouTube and how to improve the experience for viewers.</p><p>Second reason is the destination, Singapore. It's going to be my second trip to Asia after speaking at the C# Corner Conference 2017 in India. I have watched a number of documentaries about the city country during the past years, and the broadcast of the Formula 1 race is one of the highlights in my "sports calendar". Combining my attendance at the DCOC summit with the ability to explore the city of Singapore during two spare days, Wednesday and Saturday, sounded like an opportunity not to miss.</p><p>But hang on... JoKi, I thought you'd be a software crafter. How does this relate to your in-person attendance?‌‌In my case this might be the answer: "<strong>Online community managers</strong>: manage online tech communities on Discord, Telegram, Slack or other platforms (1000+ members/subscribers/followers)." - I founded and I'm still co-managing the two largest communities in Mauritius, namely <a href="https://www.mscc.mu/">Mauritius Software Craftsmanship Community</a> (MSCC) and <a href="https://gdg.community.dev/gdg-mauritius/">GDG Mauritius</a> with a combined total count of over 4,000 members. With social media presence on X/Twitter, Facebook, and LinkedIn reaching almost 9,000 people. Even our YouTube channel has close to 400 subscribers.</p><p>So, why attending in-person? The direct interaction with other peers is priceless. Getting into a conversation with other attendees is so much easier than in online sessions (with chats). The learning factor from others' experience is magnitudes higher, more relatable and up close personal. Similar to our regular user group meetings.</p><h2 id="travelling-to-and-fro-and-how">Travelling to and fro, and how</h2><p>Similar to <a href="https://jochen.kirstaetter.name/ssa-community-summit-2023/">previous trips</a> I decided to travel light again, despite being out of the country for the six days. A small carry-on trolley for a bare minimum of clothes topped up with my daily backpack containing all kind of equipment.</p><p>The focus was on everything using a single connector, USB-C. Hence I assembled the following equipment to bring along.</p><ul><li>Lenovo Chromebook (USB-C charging)</li><li>Google Pixel 6a (USB-C charging)</li><li>Google Buds Pro (ANC and USB-C charging)</li><li>Valco VMK20 (ANC and USB-C charging)</li><li>10,000 mAh battery power pack (USB-C charging)</li><li>Hama 60W multi-plug USB-C charger (4 outlets)</li><li>Cables. Lots of cables. USB cables, an HDMI cable, and a network cable. Let's see whether I get to hack that SmartTV at the hotel. 🤣</li></ul><p>Regular readers might have had a good idea already.</p><p>At a certain stage I was even considering to leave any laptop at home. But then, why would you go to a Google Summit without a laptop, especially without a Chromebook? For one of the workshops it was communicated upfront that you have to have a laptop with you. So there we go. Unfortunately, I didn't pack my lavalier microphone which would have been very handy for some ad hoc on the spot recordings / live broadcast from the summit or from Singapore.</p><p>The choice of airline was easier for this trip. Although there are direct flights from Mauritius to Singapore, operated by Air Mauritius, there are a limited number of flights per week only. Such a flight would take roughly eight hours but the available options didn't fit well with the agenda scheduled. In consequence, I looked at the multiple flights per day on Emirates. and booked the round-trip taking into account that it took twice the time including a short stop-over in Dubai. Surprisingly, the price difference between those two choices is marginal. The flexibility advantage is impressive and actually I'm fewer days out of office than otherwise. Who'd expected that?</p><p>Speaking of expectations, Singapore requires all foreign travellers to submit the <a href="https://www.ica.gov.sg/enter-transit-depart/entering-singapore/sg-arrival-card">SG Arrival Card</a> (SGAC) <strong>before</strong> arriving. There are two options to complete that requirement. Either you use their SGAC e-Service online or you install their MyICA Mobile application. I went for the later and it was done after a few clicks here and there, and uploading a scan of my passport. The SGAC is equivalent to the All-in-One Health Form when someone travels to Mauritius.</p><h2 id="touchdown-singapore">Touchdown Singapore</h2><p>After the welcoming stop-over at the Emirates Business Lounge at the Dubai airport I arrived a little bit ahead of time in Singapore. And wow, what a difference the airport is.</p><h3 id="changi-airport-and-public-transport">Changi Airport and public transport</h3><p>I've been to a few airports around the world so far and Changi is by far the most impressive one. Think of an airport inside a huge shopping mall and entertainment facility and you might get an idea about it. This thing is huge! Did I mention that free WiFi is offered everywhere?</p><figure class="kg-card kg-image-card kg-width-wide kg-card-hascaption"><img src="https://jochen.kirstaetter.name/content/images/2024/01/PXL_20240123_134933957.MP.jpg" class="kg-image" alt="Developer Creators and Online Communities Summit" srcset="https://jochen.kirstaetter.name/content/images/size/w600/2024/01/PXL_20240123_134933957.MP.jpg 600w, https://jochen.kirstaetter.name/content/images/2024/01/PXL_20240123_134933957.MP.jpg 960w"><figcaption>The Jewel at Changi airport in Singapore</figcaption></figure><p>Next task was to purchase one of those NFC cards for public transport. To my understanding there are at least two possibilities - ezLink and SimpleGo. I spent like $S 10 for the ezLink card which came pre-loaded with a balance of $S 5 to ride the MRT lines and busses.</p><p>As for mobile data it was even easier. Ahead of my trip I purchased a <a href="https://www.singtel.com/personal/products-services/mobile/prepaid-plans/hi-tourist">SingTel Tourist eSIM</a> for their 5G network online. Then you install their hi!App and you can register/activate the eSIM card in your mobile <strong>after</strong> you have connection with their network. A few identification steps and confirmation emails later I was able to use their 5G data network instantly. Checkout the speed rates.</p><figure class="kg-card kg-embed-card kg-card-hascaption"><blockquote class="twitter-tweet"><p lang="en" dir="ltr">OMG ! That&#39;s a quick test while riding the Skytrain between terminals at Changi airport, Singapore.<br><br>500+M ps! 😳😳😳<a href="https://t.co/UF1nsgByAX">https://t.co/UF1nsgByAX</a></p>&mdash; Jochen Kirstätter (JoKi) (@JKirstaetter) <a href="https://twitter.com/JKirstaetter/status/1749798217540374796?ref_src=twsrc%5Etfw">January 23, 2024</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

<figcaption>Ludicrous speed rates on the SingTel 5G network - Impressive!</figcaption></figure><p>Another positive surprise was the automated immigration and passport stations. Armored with your passport, the SGAC code received and yourself you have everything to get through. For me, it was as smooth as the automated passport stations at German airports. Maybe even smoother...</p><figure class="kg-card kg-embed-card kg-card-hascaption"><blockquote class="twitter-tweet"><p lang="en" dir="ltr">Passport/security check out at the airport... Whizz, done.<br><br>Scan passport, scan digital SGAC, scan finger, ✅<br><br>Less than 10 minutes. The queuing took most of the time. 2 people ahead of me.<a href="https://twitter.com/hashtag/GoogleDCOC?src=hash&amp;ref_src=twsrc%5Etfw">#GoogleDCOC</a> <a href="https://twitter.com/hashtag/GoogleDevCommunity?src=hash&amp;ref_src=twsrc%5Etfw">#GoogleDevCommunity</a></p>&mdash; Jochen Kirstätter (JoKi) (@JKirstaetter) <a href="https://twitter.com/JKirstaetter/status/1749807519470600368?ref_src=twsrc%5Etfw">January 23, 2024</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

<figcaption>Blazing through the passport &amp; immigration check at Changi airport in Singapore</figcaption></figure><p>Next, I went straight to the MRT station at Changi airport to catch a ride into the city. To get around I installed the MyTransport.SG mobile application which provides the network layout of the different MRT lines and the bus lines with all stations. Alternatively, Google Maps works just fine, too. Actually, I downloaded the map of Singapore for offline use. You know, just in case I might get lost without data network, etc.</p><h3 id="chinatown-and-staying-at-a-capsule-hotel">Chinatown and staying at a capsule hotel</h3><p>I boarded the MRT green line shortly after 22.00 hrs, and had to change to the Downtown (blue) line at Expo station before arriving at the DT 19 - Chinatown - station. Despite the late hour businesses and restaurants are still buzzing over there. Glad I chose this suburb to stay the first night. At least, I knew there would be various options to have a tasty dinner, and opportunities to shop anything I might have forgotten to bring along.</p><p>The capsule hotel I booked was within 5 minutes walking distance from the station exit Pagoda Street, and following the directions on Google Maps got me there easily. A quick scan of my passport at their automated check-in kiosk checked me in, and I received the key card in exchange. Again, really smooth and user-friendly processing. Here are a few impressions.</p><figure class="kg-card kg-gallery-card kg-width-wide kg-card-hascaption"><div class="kg-gallery-container"><div class="kg-gallery-row"><div class="kg-gallery-image"><img src="https://jochen.kirstaetter.name/content/images/2024/01/PXL_20240123_152238217.jpg" width="960" height="1280" alt="Developer Creators and Online Communities Summit" srcset="https://jochen.kirstaetter.name/content/images/size/w600/2024/01/PXL_20240123_152238217.jpg 600w, https://jochen.kirstaetter.name/content/images/2024/01/PXL_20240123_152238217.jpg 960w" sizes="(min-width: 720px) 720px"></div><div class="kg-gallery-image"><img src="https://jochen.kirstaetter.name/content/images/2024/01/PXL_20240123_171443470.jpg" width="960" height="720" alt="Developer Creators and Online Communities Summit" srcset="https://jochen.kirstaetter.name/content/images/size/w600/2024/01/PXL_20240123_171443470.jpg 600w, https://jochen.kirstaetter.name/content/images/2024/01/PXL_20240123_171443470.jpg 960w" sizes="(min-width: 720px) 720px"></div><div class="kg-gallery-image"><img src="https://jochen.kirstaetter.name/content/images/2024/01/PXL_20240123_152541207.jpg" width="960" height="1280" alt="Developer Creators and Online Communities Summit" srcset="https://jochen.kirstaetter.name/content/images/size/w600/2024/01/PXL_20240123_152541207.jpg 600w, https://jochen.kirstaetter.name/content/images/2024/01/PXL_20240123_152541207.jpg 960w" sizes="(min-width: 720px) 720px"></div></div><div class="kg-gallery-row"><div class="kg-gallery-image"><img src="https://jochen.kirstaetter.name/content/images/2024/01/PXL_20240123_154929208.jpg" width="960" height="1280" alt="Developer Creators and Online Communities Summit" srcset="https://jochen.kirstaetter.name/content/images/size/w600/2024/01/PXL_20240123_154929208.jpg 600w, https://jochen.kirstaetter.name/content/images/2024/01/PXL_20240123_154929208.jpg 960w" sizes="(min-width: 720px) 720px"></div><div class="kg-gallery-image"><img src="https://jochen.kirstaetter.name/content/images/2024/01/PXL_20240123_155937259-2.jpg" width="960" height="752" alt="Developer Creators and Online Communities Summit" srcset="https://jochen.kirstaetter.name/content/images/size/w600/2024/01/PXL_20240123_155937259-2.jpg 600w, https://jochen.kirstaetter.name/content/images/2024/01/PXL_20240123_155937259-2.jpg 960w" sizes="(min-width: 720px) 720px"></div><div class="kg-gallery-image"><img src="https://jochen.kirstaetter.name/content/images/2024/01/PXL_20240123_171730064.jpg" width="960" height="1802" alt="Developer Creators and Online Communities Summit" srcset="https://jochen.kirstaetter.name/content/images/size/w600/2024/01/PXL_20240123_171730064.jpg 600w, https://jochen.kirstaetter.name/content/images/2024/01/PXL_20240123_171730064.jpg 960w" sizes="(min-width: 720px) 720px"></div></div><div class="kg-gallery-row"><div class="kg-gallery-image"><img src="https://jochen.kirstaetter.name/content/images/2024/01/PXL_20240123_153759566.jpg" width="960" height="720" alt="Developer Creators and Online Communities Summit" srcset="https://jochen.kirstaetter.name/content/images/size/w600/2024/01/PXL_20240123_153759566.jpg 600w, https://jochen.kirstaetter.name/content/images/2024/01/PXL_20240123_153759566.jpg 960w" sizes="(min-width: 720px) 720px"></div><div class="kg-gallery-image"><img src="https://jochen.kirstaetter.name/content/images/2024/01/PXL_20240123_153946299.jpg" width="960" height="720" alt="Developer Creators and Online Communities Summit" srcset="https://jochen.kirstaetter.name/content/images/size/w600/2024/01/PXL_20240123_153946299.jpg 600w, https://jochen.kirstaetter.name/content/images/2024/01/PXL_20240123_153946299.jpg 960w" sizes="(min-width: 720px) 720px"></div></div></div><figcaption>Exploring Chinatown by night on the hunt for food and accommodation (capsule hotel)</figcaption></figure><p>With the key card you get access to the different levels and amenities of the hotel. I reached my sleeping capsule, dropped of the luggage in the designated, key card secured locker storage, and then went on tour in Chinatown for dinner. I wasn't sure how long restaurants would be open but thought that probably midnight might be a closing time anywhere. In short distance across the hotel I found a place with yummy-looking dishes and I decided to give it shot. I mean, what could possible go wrong? BTW, the ratings on Google Maps for that joint are positive and their range of dishes offered is wide.</p><p>Around 1:30 hrs in the morning I finally went to sleep in my capsule. Well fed, cleaned up after having had a shower in the common washroom area of the hotel, and tired from the long trip.</p><h2 id="day-1">Day 1</h2><p>Exploration time!</p><p>First day in Singapore had no fixed agenda and it gave me the opportunity to explore the city freely. After a few hours of rest and the generous offer by the capsule hotel to store my luggage beyond the checkout I asked them for a few must-visit places in town.</p><h3 id="exploring-chinatown">Exploring Chinatown</h3><p>As I spent the night in Chinatown what's more obvious than to discover the suburban during the morning hours? A quick check on Google Maps that the famous <a href="https://maps.app.goo.gl/BgT3dcyWb4HabU7p7">Buddha Tooth Relic Temple</a> is literally just around the corner. By the time I got there prayers were still in full swing and it has an enlightening experience to stay for a while</p><figure class="kg-card kg-gallery-card kg-width-wide kg-card-hascaption"><div class="kg-gallery-container"><div class="kg-gallery-row"><div class="kg-gallery-image"><img src="https://jochen.kirstaetter.name/content/images/2024/01/PXL_20240124_010812001.jpg" width="960" height="720" alt="Developer Creators and Online Communities Summit" srcset="https://jochen.kirstaetter.name/content/images/size/w600/2024/01/PXL_20240124_010812001.jpg 600w, https://jochen.kirstaetter.name/content/images/2024/01/PXL_20240124_010812001.jpg 960w" sizes="(min-width: 720px) 720px"></div><div class="kg-gallery-image"><img src="https://jochen.kirstaetter.name/content/images/2024/01/PXL_20240124_012931903.jpg" width="960" height="588" alt="Developer Creators and Online Communities Summit" srcset="https://jochen.kirstaetter.name/content/images/size/w600/2024/01/PXL_20240124_012931903.jpg 600w, https://jochen.kirstaetter.name/content/images/2024/01/PXL_20240124_012931903.jpg 960w" sizes="(min-width: 720px) 720px"></div><div class="kg-gallery-image"><img src="https://jochen.kirstaetter.name/content/images/2024/01/PXL_20240124_013321780.MP.jpg" width="960" height="1421" alt="Developer Creators and Online Communities Summit" srcset="https://jochen.kirstaetter.name/content/images/size/w600/2024/01/PXL_20240124_013321780.MP.jpg 600w, https://jochen.kirstaetter.name/content/images/2024/01/PXL_20240124_013321780.MP.jpg 960w" sizes="(min-width: 720px) 720px"></div></div><div class="kg-gallery-row"><div class="kg-gallery-image"><img src="https://jochen.kirstaetter.name/content/images/2024/01/PXL_20240124_012722114.jpg" width="960" height="720" alt="Developer Creators and Online Communities Summit" srcset="https://jochen.kirstaetter.name/content/images/size/w600/2024/01/PXL_20240124_012722114.jpg 600w, https://jochen.kirstaetter.name/content/images/2024/01/PXL_20240124_012722114.jpg 960w" sizes="(min-width: 720px) 720px"></div><div class="kg-gallery-image"><img src="https://jochen.kirstaetter.name/content/images/2024/01/PXL_20240124_012603370.jpg" width="960" height="720" alt="Developer Creators and Online Communities Summit" srcset="https://jochen.kirstaetter.name/content/images/size/w600/2024/01/PXL_20240124_012603370.jpg 600w, https://jochen.kirstaetter.name/content/images/2024/01/PXL_20240124_012603370.jpg 960w" sizes="(min-width: 720px) 720px"></div></div><div class="kg-gallery-row"><div class="kg-gallery-image"><img src="https://jochen.kirstaetter.name/content/images/2024/01/PXL_20240124_014321537.jpg" width="960" height="720" alt="Developer Creators and Online Communities Summit" srcset="https://jochen.kirstaetter.name/content/images/size/w600/2024/01/PXL_20240124_014321537.jpg 600w, https://jochen.kirstaetter.name/content/images/2024/01/PXL_20240124_014321537.jpg 960w" sizes="(min-width: 720px) 720px"></div><div class="kg-gallery-image"><img src="https://jochen.kirstaetter.name/content/images/2024/01/PXL_20240124_021742903.jpg" width="640" height="853" alt="Developer Creators and Online Communities Summit" srcset="https://jochen.kirstaetter.name/content/images/size/w600/2024/01/PXL_20240124_021742903.jpg 600w, https://jochen.kirstaetter.name/content/images/2024/01/PXL_20240124_021742903.jpg 640w"></div></div></div><figcaption>Strolling around Chinatown and discovering amazing locations</figcaption></figure><p>Down that same road I went to visit the <a href="https://maps.app.goo.gl/mgtLCYEhhpz8QE4q9">Sri Mariamman Temple</a> and there also had been prayers. Taking into consideration that Thaipoosam Cavadee was on Thursday I assumed devotees would be at the temple for prayers. Although I went back through Pagoda Street towards the colonial street shops I only saw the <a href="https://maps.app.goo.gl/J9FwQ2BCH7nTPpri9">Jamae (Chulia) Mosque</a> from a short distance but didn't go there. I was reminded of Mauritius with those three places in close, peaceful coexistence.</p><figure class="kg-card kg-image-card kg-width-full"><img src="https://jochen.kirstaetter.name/content/images/2024/01/PXL_20240124_015502071.jpg" class="kg-image" alt="Developer Creators and Online Communities Summit" srcset="https://jochen.kirstaetter.name/content/images/size/w600/2024/01/PXL_20240124_015502071.jpg 600w, https://jochen.kirstaetter.name/content/images/size/w1000/2024/01/PXL_20240124_015502071.jpg 1000w, https://jochen.kirstaetter.name/content/images/2024/01/PXL_20240124_015502071.jpg 1280w"></figure><h3 id="the-bay-area">The Bay area</h3><p>Closing the loop through Chinatown I went back to the TE 18 - Maxwell - station of the MRT and headed to the line's final destination in the south east: TE 22 - Gardens by the Bay. The weather was holding and so I first went to the <a href="https://maps.app.goo.gl/efqSDTzKPh5W78jq5">Marina Barrage</a> to get a view of the barrage bridge and dam, and the many ships out on the sea. The barrage building itself is super interesting as there are several slopes that allow you to walk on the top of it.</p><p>Despite the light rain, yeah I brought a lightweight rain jacket with me, I then ventured to the Gardens by the Bay. Coming from the south I first visited the <a href="https://maps.app.goo.gl/4rq4xT9xHx9WWhvTA">Kingfisher Lake</a> with its small waterfalls and statues. Passing the Water Lily Pond and Sun Pavilion I headed straight to the Floral Clock. From there I got tickets for the <a href="https://maps.app.goo.gl/QdCyL4Va9VKamioj6">Cloud Forest</a> and the <a href="https://maps.app.goo.gl/KtYYSufCkMQ1EJ2J6">Flower Dome</a>.</p><p>The Cloud Forest with its indoor waterfall and six levels of nature exploration is impressive and amazing to visit.</p><figure class="kg-card kg-gallery-card kg-width-wide kg-card-hascaption"><div class="kg-gallery-container"><div class="kg-gallery-row"><div class="kg-gallery-image"><img src="https://jochen.kirstaetter.name/content/images/2024/01/PXL_20240124_033113263.jpg" width="960" height="720" alt="Developer Creators and Online Communities Summit" srcset="https://jochen.kirstaetter.name/content/images/size/w600/2024/01/PXL_20240124_033113263.jpg 600w, https://jochen.kirstaetter.name/content/images/2024/01/PXL_20240124_033113263.jpg 960w" sizes="(min-width: 720px) 720px"></div><div class="kg-gallery-image"><img src="https://jochen.kirstaetter.name/content/images/2024/01/PXL_20240124_034036625.jpg" width="960" height="419" alt="Developer Creators and Online Communities Summit" srcset="https://jochen.kirstaetter.name/content/images/size/w600/2024/01/PXL_20240124_034036625.jpg 600w, https://jochen.kirstaetter.name/content/images/2024/01/PXL_20240124_034036625.jpg 960w" sizes="(min-width: 720px) 720px"></div><div class="kg-gallery-image"><img src="https://jochen.kirstaetter.name/content/images/2024/01/PXL_20240124_042531770.jpg" width="960" height="1280" alt="Developer Creators and Online Communities Summit" srcset="https://jochen.kirstaetter.name/content/images/size/w600/2024/01/PXL_20240124_042531770.jpg 600w, https://jochen.kirstaetter.name/content/images/2024/01/PXL_20240124_042531770.jpg 960w" sizes="(min-width: 720px) 720px"></div></div><div class="kg-gallery-row"><div class="kg-gallery-image"><img src="https://jochen.kirstaetter.name/content/images/2024/01/PXL_20240124_035826625.jpg" width="960" height="720" alt="Developer Creators and Online Communities Summit" srcset="https://jochen.kirstaetter.name/content/images/size/w600/2024/01/PXL_20240124_035826625.jpg 600w, https://jochen.kirstaetter.name/content/images/2024/01/PXL_20240124_035826625.jpg 960w" sizes="(min-width: 720px) 720px"></div><div class="kg-gallery-image"><img src="https://jochen.kirstaetter.name/content/images/2024/01/PXL_20240124_043114612.jpg" width="960" height="720" alt="Developer Creators and Online Communities Summit" srcset="https://jochen.kirstaetter.name/content/images/size/w600/2024/01/PXL_20240124_043114612.jpg 600w, https://jochen.kirstaetter.name/content/images/2024/01/PXL_20240124_043114612.jpg 960w" sizes="(min-width: 720px) 720px"></div><div class="kg-gallery-image"><img src="https://jochen.kirstaetter.name/content/images/2024/01/PXL_20240124_044936967.jpg" width="960" height="1280" alt="Developer Creators and Online Communities Summit" srcset="https://jochen.kirstaetter.name/content/images/size/w600/2024/01/PXL_20240124_044936967.jpg 600w, https://jochen.kirstaetter.name/content/images/2024/01/PXL_20240124_044936967.jpg 960w" sizes="(min-width: 720px) 720px"></div></div><div class="kg-gallery-row"><div class="kg-gallery-image"><img src="https://jochen.kirstaetter.name/content/images/2024/01/PXL_20240124_045210948.jpg" width="960" height="720" alt="Developer Creators and Online Communities Summit" srcset="https://jochen.kirstaetter.name/content/images/size/w600/2024/01/PXL_20240124_045210948.jpg 600w, https://jochen.kirstaetter.name/content/images/2024/01/PXL_20240124_045210948.jpg 960w" sizes="(min-width: 720px) 720px"></div><div class="kg-gallery-image"><img src="https://jochen.kirstaetter.name/content/images/2024/01/PXL_20240124_053225960.jpg" width="960" height="720" alt="Developer Creators and Online Communities Summit" srcset="https://jochen.kirstaetter.name/content/images/size/w600/2024/01/PXL_20240124_053225960.jpg 600w, https://jochen.kirstaetter.name/content/images/2024/01/PXL_20240124_053225960.jpg 960w" sizes="(min-width: 720px) 720px"></div><div class="kg-gallery-image"><img src="https://jochen.kirstaetter.name/content/images/2024/01/PXL_20240124_055415956.jpg" width="960" height="582" alt="Developer Creators and Online Communities Summit" srcset="https://jochen.kirstaetter.name/content/images/size/w600/2024/01/PXL_20240124_055415956.jpg 600w, https://jochen.kirstaetter.name/content/images/2024/01/PXL_20240124_055415956.jpg 960w" sizes="(min-width: 720px) 720px"></div></div></div><figcaption>Impressions from the Gardens by the Bay landmarks</figcaption></figure><p>There are different sections of floral diversity which the Flower Dome has to offer. I enjoyed the smells, the tranquility in certain areas, and the massive educational factor across the dome. One could easily spend the whole day there.</p><p>As lunch time started to close in, I went along the Dragonfly Lake towards the Bayfront Ave and ended up in <a href="https://maps.app.goo.gl/oHXKYSLLPD6LeZzF9">The Shoppes at Marina Sands Bay</a>. That's like shopping heaven on Earth :)</p><p>To wrap up the tour I took the Downtown line from DT 16 - Bayfront - back to Chinatown. Stopped by at the capsule hotel to charge my mobile a bit, chatted with the family back home in Mauritius, and then grabbed my luggage to move to the booked hotel by Google. This time I caught a bus and got off the station right in front of <a href="https://maps.app.goo.gl/e9FSir9rgPkYk6Vt8">IKEA Alexandra</a>. Our hotel - <a href="https://maps.app.goo.gl/fFCUBfDBy4ATouXR6">Momentus Hotel Alexandra</a> - is next to it.</p><p>After all the walking and discoveries during the morning and midday hours I was a bit exhausted and therefore relieved to stretch out on the bed to rest. The little time left until the official Welcome Reception next to the pool I used to review the tons of pictures I had taken, chatted a bit more with my wife and the kids, and had a refreshing shower.</p><h3 id="welcome-reception">Welcome reception</h3><p>Our organising team from Google invited us to an informal welcome/reception dinner at the Momentus Hotel to gently kick off the summit. After a brief exchange with <a href="https://www.linkedin.com/in/dirkprimbs/">Dirk Primbs</a> - asking him about getting accustomed in Canada - I took an empty chair at one of the tables and joined a group of developer creators from Hanoi, Vietnam: <a href="https://www.linkedin.com/in/huydanggdg">Huy Dang</a>, <a href="https://www.linkedin.com/in/dang-dong-9aa227193/">Dang Dong</a>, and <a href="https://www.linkedin.com/in/truongnh1992/" rel="noopener">Nguyen Hai-Truong</a>. It was interesting to learn more about their activities and how they organise events. Thanks for the pin and stickers!</p><p>Shortly after I spotted <a href="https://www.linkedin.com/in/yesayaathuman">Yesaya Athuman</a> who I missed talking to at <a href="https://jochen.kirstaetter.name/devfest-dar-es-salaam-2023/">DevFest Dar es Salaam</a>. I went over to him joining others standing and chatting about all kind of community stuff. There I got introduced to <a href="https://www.linkedin.com/in/ngkalbarczyk">Dariusz Kalbarczyk</a>, organiser of ngPolandConf, and we exchanged a bit about our common friend <a href="https://www.linkedin.com/in/dhananjaykumar07">Dhananjay Kumar</a>, organiser of ngIndia. By chance we were also joined by <a href="https://www.linkedin.com/in/mazlum-tosun-900b1812">Mazlum Tosun</a> whose YouTube videos fascinate me as he creates Google Cloud content in French and English language, and promotes them equally. We instantly spoke about common friends in the community like <a href="https://www.linkedin.com/in/ezekias-bokove">Ezekias Bokove</a>, <a href="https://www.linkedin.com/in/louis-japheth-kouassi">Louis Japheth Kouassi</a>, and <a href="https://www.linkedin.com/in/guillaume-blaquiere-38693b15">Guillaume Blaquiere</a>. While having dinner fellow creator and book author <a href="https://www.linkedin.com/in/ahsanayaz">Muhammed Ahsan Ayaz</a> spent some time and interesting stories with us.</p><figure class="kg-card kg-gallery-card kg-width-wide"><div class="kg-gallery-container"><div class="kg-gallery-row"><div class="kg-gallery-image"><img src="https://jochen.kirstaetter.name/content/images/2024/01/PXL_20240124_102040771.MP.jpg" width="960" height="617" alt="Developer Creators and Online Communities Summit" srcset="https://jochen.kirstaetter.name/content/images/size/w600/2024/01/PXL_20240124_102040771.MP.jpg 600w, https://jochen.kirstaetter.name/content/images/2024/01/PXL_20240124_102040771.MP.jpg 960w" sizes="(min-width: 720px) 720px"></div><div class="kg-gallery-image"><img src="https://jochen.kirstaetter.name/content/images/2024/01/1706108657703.jpeg" width="1290" height="968" alt="Developer Creators and Online Communities Summit" srcset="https://jochen.kirstaetter.name/content/images/size/w600/2024/01/1706108657703.jpeg 600w, https://jochen.kirstaetter.name/content/images/size/w1000/2024/01/1706108657703.jpeg 1000w, https://jochen.kirstaetter.name/content/images/2024/01/1706108657703.jpeg 1290w" sizes="(min-width: 720px) 720px"></div><div class="kg-gallery-image"><img src="https://jochen.kirstaetter.name/content/images/2024/01/1706108656940.jpeg" width="1290" height="968" alt="Developer Creators and Online Communities Summit" srcset="https://jochen.kirstaetter.name/content/images/size/w600/2024/01/1706108656940.jpeg 600w, https://jochen.kirstaetter.name/content/images/size/w1000/2024/01/1706108656940.jpeg 1000w, https://jochen.kirstaetter.name/content/images/2024/01/1706108656940.jpeg 1290w" sizes="(min-width: 720px) 720px"></div></div><div class="kg-gallery-row"><div class="kg-gallery-image"><img src="https://jochen.kirstaetter.name/content/images/2024/01/IMG_2937.jpeg" width="960" height="720" alt="Developer Creators and Online Communities Summit" srcset="https://jochen.kirstaetter.name/content/images/size/w600/2024/01/IMG_2937.jpeg 600w, https://jochen.kirstaetter.name/content/images/2024/01/IMG_2937.jpeg 960w" sizes="(min-width: 720px) 720px"></div><div class="kg-gallery-image"><img src="https://jochen.kirstaetter.name/content/images/2024/01/IMG_8359.JPG" width="960" height="960" alt="Developer Creators and Online Communities Summit" srcset="https://jochen.kirstaetter.name/content/images/size/w600/2024/01/IMG_8359.JPG 600w, https://jochen.kirstaetter.name/content/images/2024/01/IMG_8359.JPG 960w" sizes="(min-width: 720px) 720px"></div></div></div></figure><p>With the evening progressing and having had dinner from the buffet you could observe the forming of multiple groups based on either geographical vicinity or established connections on Discord. It always amazes me how easy it is to connect with other during such in-person gatherings. Together with Yesaya, I then sat down with <a href="https://www.linkedin.com/in/daisyfaithauma">Daisy Auma</a> and <a href="https://www.linkedin.com/in/ezinne-osuamadi-216167146">Ezinne Osuamadi</a> to learn more about their professional whereabouts and community involvements. It was actually fascinating to learn that Daisy moved from Kenya to the UK, whereas Ezinne is from Nigeria and working in Germany since a few years. </p><blockquote>The world is such a small village after all.</blockquote><p>During the evening I got to meet other participants from Turkmenistan, Kazakhstan, Uzbekistan, Mongolia, France, Italy, India, Bangladesh, Indonesia, and many more countries. Each single one with fascinating stories of content creation and community engagements. Very inspiring actually!</p><h2 id="day-2">Day 2</h2><p>Finally the day has arrived! The summit is happening officially. A shuttle bus took us the short distance from the hotel to the Mapletree Business City where <a href="https://maps.app.goo.gl/5HqD7QUAQxvWLWrj7">Google Singapore</a> has its office.</p><h3 id="dcoc-summit">DCOC Summit</h3><p>An empty stomach isn't capable to study. Hence breakfast buffet had been offered by Google. A number of conversations from last night were reignited and new conversations came to life. Big Hello's and cheers everywhere around; this summit was so inclusive and welcoming.</p><p>Our two Masters of Ceremony <a href="https://www.linkedin.com/in/alicja-heisig-chiarello/">Alicja Heisig-Chiarello</a> and <a href="https://www.linkedin.com/in/dirkprimbs/">Dirk Primbs</a> launched the Summit officially and also welcomed everyone on the live stream. Meanwhile our two radio / live streaming moderators <a href="https://www.linkedin.com/in/nathalie-pereira-063a513/">Nathalie Pereira</a> and <a href="https://www.linkedin.com/in/alfredomorresi/">Alfredo Morresi</a> had started already. Oh yes, amazingly the whole summit was a hybrid event with in-person and online participation. </p><figure class="kg-card kg-gallery-card kg-width-wide"><div class="kg-gallery-container"><div class="kg-gallery-row"><div class="kg-gallery-image"><img src="https://jochen.kirstaetter.name/content/images/2024/01/PXL_20240124_235148317.jpg" width="960" height="1280" alt="Developer Creators and Online Communities Summit" srcset="https://jochen.kirstaetter.name/content/images/size/w600/2024/01/PXL_20240124_235148317.jpg 600w, https://jochen.kirstaetter.name/content/images/2024/01/PXL_20240124_235148317.jpg 960w" sizes="(min-width: 720px) 720px"></div><div class="kg-gallery-image"><img src="https://jochen.kirstaetter.name/content/images/2024/01/1706509845551.jpeg" width="1179" height="885" alt="Developer Creators and Online Communities Summit" srcset="https://jochen.kirstaetter.name/content/images/size/w600/2024/01/1706509845551.jpeg 600w, https://jochen.kirstaetter.name/content/images/size/w1000/2024/01/1706509845551.jpeg 1000w, https://jochen.kirstaetter.name/content/images/2024/01/1706509845551.jpeg 1179w" sizes="(min-width: 720px) 720px"></div><div class="kg-gallery-image"><img src="https://jochen.kirstaetter.name/content/images/2024/01/PXL_20240125_013946374.MP.jpg" width="960" height="1275" alt="Developer Creators and Online Communities Summit" srcset="https://jochen.kirstaetter.name/content/images/size/w600/2024/01/PXL_20240125_013946374.MP.jpg 600w, https://jochen.kirstaetter.name/content/images/2024/01/PXL_20240125_013946374.MP.jpg 960w" sizes="(min-width: 720px) 720px"></div></div><div class="kg-gallery-row"><div class="kg-gallery-image"><img src="https://jochen.kirstaetter.name/content/images/2024/01/20240125_092722.jpg" width="960" height="720" alt="Developer Creators and Online Communities Summit" srcset="https://jochen.kirstaetter.name/content/images/size/w600/2024/01/20240125_092722.jpg 600w, https://jochen.kirstaetter.name/content/images/2024/01/20240125_092722.jpg 960w" sizes="(min-width: 720px) 720px"></div><div class="kg-gallery-image"><img src="https://jochen.kirstaetter.name/content/images/2024/01/IMG_8482.jpg" width="960" height="1280" alt="Developer Creators and Online Communities Summit" srcset="https://jochen.kirstaetter.name/content/images/size/w600/2024/01/IMG_8482.jpg 600w, https://jochen.kirstaetter.name/content/images/2024/01/IMG_8482.jpg 960w" sizes="(min-width: 720px) 720px"></div><div class="kg-gallery-image"><img src="https://jochen.kirstaetter.name/content/images/2024/01/PXL_20240125_095630367.MP.jpg" width="960" height="1019" alt="Developer Creators and Online Communities Summit" srcset="https://jochen.kirstaetter.name/content/images/size/w600/2024/01/PXL_20240125_095630367.MP.jpg 600w, https://jochen.kirstaetter.name/content/images/2024/01/PXL_20240125_095630367.MP.jpg 960w" sizes="(min-width: 720px) 720px"></div></div><div class="kg-gallery-row"><div class="kg-gallery-image"><img src="https://jochen.kirstaetter.name/content/images/2024/01/IMG_0729.jpg" width="960" height="1280" alt="Developer Creators and Online Communities Summit" srcset="https://jochen.kirstaetter.name/content/images/size/w600/2024/01/IMG_0729.jpg 600w, https://jochen.kirstaetter.name/content/images/2024/01/IMG_0729.jpg 960w" sizes="(min-width: 720px) 720px"></div><div class="kg-gallery-image"><img src="https://jochen.kirstaetter.name/content/images/2024/01/PXL_20240125_101828139.MP.jpg" width="960" height="1094" alt="Developer Creators and Online Communities Summit" srcset="https://jochen.kirstaetter.name/content/images/size/w600/2024/01/PXL_20240125_101828139.MP.jpg 600w, https://jochen.kirstaetter.name/content/images/2024/01/PXL_20240125_101828139.MP.jpg 960w" sizes="(min-width: 720px) 720px"></div></div></div></figure><p>BTW, here's the agenda: <a href="https://rsvp.withgoogle.com/events/developer-creators-and-online-communities-summit/agenda">https://rsvp.withgoogle.com/events/developer-creators-and-online-communities-summit/agenda</a> </p><p>Next up <a href="https://www.linkedin.com/in/jantan">Janise Tan</a> welcomed us to Singapore and the SEA developer community landscape giving us some details about the region, its numbers regarding to communities and activities. Fun fact, while introducing Singapore to the audience she highlighted some of the key factors of the city's success which miraculously match the secret ingredients being a successful content creator online or running thriving communities.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://jochen.kirstaetter.name/content/images/2024/02/PXL_20240125_020831262.jpg" class="kg-image" alt="Developer Creators and Online Communities Summit" srcset="https://jochen.kirstaetter.name/content/images/size/w600/2024/02/PXL_20240125_020831262.jpg 600w, https://jochen.kirstaetter.name/content/images/2024/02/PXL_20240125_020831262.jpg 960w" sizes="(min-width: 720px) 720px"><figcaption>Shared key success factors among Singapore and content creation online</figcaption></figure><p>True to the nature of a hybrid summit, we then watched the Creator keynote as a remote session with <a href="https://www.linkedin.com/in/stephrwong/">Stephanie Wong</a>. After the <a href="https://twitter.com/GoogleCloudTech">Google Cloud Tech</a> X/Twitter Space in April last year about <a href="https://x.com/GoogleCloudTech/status/1646544002085269506?s=20">How to make the most of Innovators Plus</a> subscription I was eager to meet Stephanie IRL. Hmm, didn't happen this time...</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://jochen.kirstaetter.name/content/images/2024/02/PXL_20240125_022750294.jpg" class="kg-image" alt="Developer Creators and Online Communities Summit" srcset="https://jochen.kirstaetter.name/content/images/size/w600/2024/02/PXL_20240125_022750294.jpg 600w, https://jochen.kirstaetter.name/content/images/2024/02/PXL_20240125_022750294.jpg 960w" sizes="(min-width: 720px) 720px"><figcaption>Content creation is about telling a story</figcaption></figure><p>Her talk gave some good insights based on her long-year experience as a successful content creator. Building and telling a concise story is one of those golden aspects to take into consideration.</p><p>Got an idea how <a href="https://www.home-assistant.io/">Home Assistant</a> started? Well, I didn't know until watching the Online communities keynote by <a href="https://www.linkedin.com/in/schoutsen/">Paulus Schoutsen</a> who started one of the largest open-source projects on GitHub based on the basic need to / problem of improving home automation. The main takeaway for me was to create and nourish a culture of inclusive, friendly, and safe online community with gender-neutral terms.</p><p>The following panel shared more tips on being successful creating content as well as entertaining a healthy community. Very helpful information has been shared by Stephanie and Paulus.</p><p>After the well-deserved morning break that allowed us to reflect and network we got an Intro to Gemini, presented by <a href="https://www.linkedin.com/in/dirkprimbs/">Dirk Primbs</a>.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://jochen.kirstaetter.name/content/images/2024/02/PXL_20240125_034133638.jpg" class="kg-image" alt="Developer Creators and Online Communities Summit" srcset="https://jochen.kirstaetter.name/content/images/size/w600/2024/02/PXL_20240125_034133638.jpg 600w, https://jochen.kirstaetter.name/content/images/2024/02/PXL_20240125_034133638.jpg 960w" sizes="(min-width: 720px) 720px"><figcaption>Recent timeline of AI development and milestones achieved by Google</figcaption></figure><p>During the past decade there had been major breakthroughs in the field of Artificial Intelligence (AI). And although these days most people might talk about AI in the context of conversational bots or generative content creation there have been more highlights, i.e. in research &amp; development sector, in the medical sector, and others. One should also understand that Machine Learning (ML) and Artificial Intelligence go way further back into the past than a decade but it's the magnitude of advancements that has happened recently only thanks to broader access to information and more capable computing power thanks to hyper-scaling data centres.</p><h3 id="breakout-sessions-i-attended">Breakout sessions I attended</h3><p>Choosing a session was tough because all breakouts covered interesting topics. Here are the ones I found most attractive:</p><ul><li>Tips on creating a winning content strategy for your YouTube channel<br>Ever wondered how YouTube handles recommendations? <a href="https://www.linkedin.com/in/nptra/">Tra Nguyen</a> gave us a few insights and tips:<br>✅ Know your audience's needs and adapt accordingly<br>✅ Focus on your audience and the algorithm will follow<br>✅ Keep experimenting!</li><li>The Simple Superpowers of Mozilla Hubs Part 1: Unleashing Innovation Through Community<br>I was intrigued about a Mozilla session at a Google event, and had never heard about <a href="https://hubs.mozilla.com/">Hubs</a> before. It's a private, virtual 3D world with endless possibilities of collaboration, according to <a href="https://www.linkedin.com/in/michael-morran/">Michael Morran</a>. I'm wondering whether this could be a feature for the <a href="https://conference.mscc.mu/">Developers Conference 2024</a> in Mauritius.</li><li>Mastering Personalized Bot Build: A Discord App-building Workshop<br>With just a few lines of code you can create your own bot(s) for Discord. <a href="https://www.linkedin.com/in/dirkprimbs/">Dirk Primbs</a> explained to us that bots are literally treated as a Discord user account with permissions granted to react to certain events. The actual functionality of such a bot is down to your imagination.</li><li>Podcasting on YouTube<br>Following the <a href="https://www.theverge.com/23891397/google-podcasts-youtube-spotify-alternatives-pocket-casts">sunsetting of Google Podcasts</a> I wanted to know what's next. Thankfully <a href="https://sg.linkedin.com/in/russell-yapjunkai">Russell Yap</a> had the right content for my curiousity. However with their move to YouTube Podcasts and YouTube Music I'm not thrilled at all, given that both services are not available in Mauritius. Plus, it requires Premium subscription to enable background play.</li></ul><p>Whew, people, I was exhausted after that whole day of high-value information. Lots of new impulses and aspects to reflect on. The complete (raw) recording is accessible here: <a href="https://rsvp.withgoogle.com/events/developer-creators-and-online-communities-summit/sessions/radio-studio-pre-show">Radio studio pre-show</a>. Most likely post-processing might is going to chop the stream into individual sessions (soon).</p><p>Lastly, our wonderful masters of ceremony Alicja and Dirk wrapped up the day with their closing remarks, informing us about the obligatory group photo, and how we are going to spent the evening together having dinner.</p><h3 id="networking-dinner">Networking dinner</h3><p>Remaining in the same office building we went upstairs to the 30th floor. There you have an amazing over Singapore. Can't remember how many panorama shots I took but I must have been in each single corner of the building.</p><p>Over dinner more networking and conversations happened. This time I buddied with fellow creators <a href="https://www.linkedin.com/in/codercatdev/">Alex Patterson</a> who runs <a href="https://codingcat.dev/">CodingCat.dev</a> and <a href="https://www.linkedin.com/in/campbelljai">Jai Campbell</a> who's a Cloud Architect from the UK. Most interestingly we talked mainly about Singapore, discontinued food products and healthy nutrition, and about a variety of documentaries broadcasted on Netflix.</p><h3 id="ikea">IKEA</h3><p>Back at the hotel I "had to go" to IKEA, of course. Not because of me but rather due to the shopping list of my beloved wife. Given the dimensions of my carry-on luggage I could purchase a few smaller, lighter items only. The most important, pressing ones so to speak.</p><h3 id="more-networking">More Networking</h3><p>Back at the hotel I didn't even bother to go upstairs to the room but stayed right away down in the lobby joining <a href="https://www.linkedin.com/in/karenhsieh/">Karen Hsieh</a>, <a href="https://www.linkedin.com/in/iamhlb/">Liang-Bin Hsueh</a>, and a local friend of his. We kind of picked up the conversation(s) from earlier today. It was interesting to learn more about Taiwan, Mandarin language, and Chinese/Asian culture. Likewise they were open to learn more about Mauritius.</p><p>Meanwhile <a href="https://www.linkedin.com/in/ahsanayaz">Muhammed Ahsan Ayaz</a> reached out to me asking where I would be around. I suggested to him to join us down in the hotel lobby. Already last week Ahsan posted in our DCOC summit channel on Discord and kindly offered physical copies of his updated, second edition book <a href="https://amzn.to/47PV9ra">Angular Cookbook</a>. I'm really happy about this addition to our community's book library. </p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://jochen.kirstaetter.name/content/images/2024/01/1706607127753.jpeg" class="kg-image" alt="Developer Creators and Online Communities Summit" srcset="https://jochen.kirstaetter.name/content/images/size/w600/2024/01/1706607127753.jpeg 600w, https://jochen.kirstaetter.name/content/images/size/w1000/2024/01/1706607127753.jpeg 1000w, https://jochen.kirstaetter.name/content/images/2024/01/1706607127753.jpeg 1280w" sizes="(min-width: 720px) 720px"><figcaption>Got a signed copy of the Angular Cookbook, 2nd Edition by <a href="https://www.linkedin.com/in/ahsanayaz">Muhammed Ahsan Ayaz</a></figcaption></figure><p>Funnily, he was a bit surprised when I asked him to have the book signed by him. "That's the first time someone is asking for a signature!" - I'm grateful for this. How often do you have a chance to meet a book author in person?</p><p>Another summit fellow, <a href="https://www.linkedin.com/in/robertheo-rt/">Robert Theo</a> from Indonesia, also got a signed copy and he then joined our little group for more networking fun. From there on we spoke a lot about Indonesia, Taiwan, Mauritius, food and cultural aspects, and so forth. Time was flying.</p><h2 id="day-3">Day 3</h2><p>That night I managed to catch a few more Zzzz's, and like the previous morning we took the provided shuttle to get to Google Singapore. Rinse and repeat, one might think. Absolutely not, today was community day!</p><h3 id="dcoc-summit-1">DCOC Summit</h3><p>Following yesterday's sessions mainly provided by Googlers and partners, the content for today was sourced from the community itself. A total of nine creators offered their knowledge and expertise. Plus, the various time slots in the podcast studio. Our fantastic masters of ceremony - Alicja and Nathalie - launched the day with a brief overview of what to expect and introduced the speakers. Each presenter had an opportunity to pitch their content in front of the audience. Another tough decision process to choose three out of nine.</p><figure class="kg-card kg-gallery-card kg-width-wide"><div class="kg-gallery-container"><div class="kg-gallery-row"><div class="kg-gallery-image"><img src="https://jochen.kirstaetter.name/content/images/2024/01/PXL_20240126_020213851.jpg" width="960" height="1377" alt="Developer Creators and Online Communities Summit" srcset="https://jochen.kirstaetter.name/content/images/size/w600/2024/01/PXL_20240126_020213851.jpg 600w, https://jochen.kirstaetter.name/content/images/2024/01/PXL_20240126_020213851.jpg 960w" sizes="(min-width: 720px) 720px"></div><div class="kg-gallery-image"><img src="https://jochen.kirstaetter.name/content/images/2024/01/PXL_20240125_100753661.jpg" width="2000" height="1506" alt="Developer Creators and Online Communities Summit" srcset="https://jochen.kirstaetter.name/content/images/size/w600/2024/01/PXL_20240125_100753661.jpg 600w, https://jochen.kirstaetter.name/content/images/size/w1000/2024/01/PXL_20240125_100753661.jpg 1000w, https://jochen.kirstaetter.name/content/images/size/w1600/2024/01/PXL_20240125_100753661.jpg 1600w, https://jochen.kirstaetter.name/content/images/size/w2400/2024/01/PXL_20240125_100753661.jpg 2400w" sizes="(min-width: 720px) 720px"></div><div class="kg-gallery-image"><img src="https://jochen.kirstaetter.name/content/images/2024/01/PXL_20240126_025330302.jpg" width="960" height="1088" alt="Developer Creators and Online Communities Summit" srcset="https://jochen.kirstaetter.name/content/images/size/w600/2024/01/PXL_20240126_025330302.jpg 600w, https://jochen.kirstaetter.name/content/images/2024/01/PXL_20240126_025330302.jpg 960w" sizes="(min-width: 720px) 720px"></div></div><div class="kg-gallery-row"><div class="kg-gallery-image"><img src="https://jochen.kirstaetter.name/content/images/2024/01/PXL_20240126_085756227.jpg" width="960" height="745" alt="Developer Creators and Online Communities Summit" srcset="https://jochen.kirstaetter.name/content/images/size/w600/2024/01/PXL_20240126_085756227.jpg 600w, https://jochen.kirstaetter.name/content/images/2024/01/PXL_20240126_085756227.jpg 960w" sizes="(min-width: 720px) 720px"></div><div class="kg-gallery-image"><img src="https://jochen.kirstaetter.name/content/images/2024/01/PXL_20240126_082748003.MP.jpg" width="960" height="721" alt="Developer Creators and Online Communities Summit" srcset="https://jochen.kirstaetter.name/content/images/size/w600/2024/01/PXL_20240126_082748003.MP.jpg 600w, https://jochen.kirstaetter.name/content/images/2024/01/PXL_20240126_082748003.MP.jpg 960w" sizes="(min-width: 720px) 720px"></div><div class="kg-gallery-image"><img src="https://jochen.kirstaetter.name/content/images/2024/01/PXL_20240126_044625862.MP.jpg" width="960" height="681" alt="Developer Creators and Online Communities Summit" srcset="https://jochen.kirstaetter.name/content/images/size/w600/2024/01/PXL_20240126_044625862.MP.jpg 600w, https://jochen.kirstaetter.name/content/images/2024/01/PXL_20240126_044625862.MP.jpg 960w" sizes="(min-width: 720px) 720px"></div></div><div class="kg-gallery-row"><div class="kg-gallery-image"><img src="https://jochen.kirstaetter.name/content/images/2024/01/20240126_144335.jpg" width="960" height="620" alt="Developer Creators and Online Communities Summit" srcset="https://jochen.kirstaetter.name/content/images/size/w600/2024/01/20240126_144335.jpg 600w, https://jochen.kirstaetter.name/content/images/2024/01/20240126_144335.jpg 960w" sizes="(min-width: 720px) 720px"></div><div class="kg-gallery-image"><img src="https://jochen.kirstaetter.name/content/images/2024/01/1706548262742-1.jpg" width="960" height="726" alt="Developer Creators and Online Communities Summit" srcset="https://jochen.kirstaetter.name/content/images/size/w600/2024/01/1706548262742-1.jpg 600w, https://jochen.kirstaetter.name/content/images/2024/01/1706548262742-1.jpg 960w" sizes="(min-width: 720px) 720px"></div></div></div></figure><h3 id="breakout-sessions-i-attended-1">Breakout sessions I attended</h3><ul><li>Making a Mark on YouTube and Google: My Story<br>First-hand shared experience always attracts my interest, and so I went to <a href="https://www.linkedin.com/in/abuanwar072/">Abu Anwar MD Abdullah</a> talk on the origins of <a href="https://youtube.com/theflutterway">The Flutter Way</a>. It's kind of amazing how he started and is now entertaining the second most followed YouTube channel in the Flutter space globally.</li><li>Podcast 101 - Dos and Don'ts<br>Starting a podcast is easy and success follows instantly? Nope, think again. Being a co-host on the <a href="https://open.spotify.com/show/0fFAunlT6yaidBjLHSN5F2">Mau Pas Konpran!?</a> podcast and having a dangling <a href="https://podcast.mscc.mu/">Talks on Software Craftsmanship</a> show I needed to know more. Thankfully <a href="https://www.linkedin.com/in/stefanolepera/">Stefano Le Pera</a> shared all the up's and down's of the <a href="https://www.youtube.com/@ChatGDG">ChatGDG</a> podcast. A lot of what he mentioned resonated with my own experience. Time to get recording again...</li><li>Generative AI for Visual Content Creation<br>Are you concerned that AI might render your job position redundant? How about leveraging Generative AI to improve your skills and be more successful? <a href="https://www.linkedin.com/in/margaretmz/">Margaret Maynard-Reid</a>, a ML Engineer / 3D Fashion Designer, gave us an overview of available types of Generative AI, and how she's benefiting from them in <a href="https://margaretmz.art/">her daily work</a>. Very useful content for my own needs.</li></ul><p>During lunch break I seized the opportunity to hang out with numerous participants. Among those are <a href="https://www.linkedin.com/in/sathishvj/">Sathish VJ</a>, <a href="https://www.linkedin.com/in/madona-wambua/">Madona Wambua</a>, <a href="https://www.linkedin.com/in/ACoAADhx5IkBPp9M-4Ls57g-KuF2NLJwwYceqr4">Neïl Rahmouni</a>, <a href="https://www.linkedin.com/in/cyruswong">Cyrus Wong Chun Yin</a> and <a href="https://linkedin.com/in/kuanhoong">Kuan Hoong Poo </a>whom I follow on social media since a while already. Another fellow creator from the Sub-Saharan Africa region, <a href="https://www.linkedin.com/in/amani-bisimwa-392ab6186">Amani Bisimwa</a>, had arrived at the summit. It was a great time to network again. </p><p>And like the previous day, the recording is available here: <a href="https://rsvp.withgoogle.com/events/developer-creators-and-online-communities-summit/sessions/welcome-to-day-3-and-introduction-to-community-driven-sessions">Welcome to Day 3 and introduction to community-driven sessions</a></p><h3 id="gardens-by-the-bay-and-spectra-at-night-">Gardens by the Bay and Spectra - At night!</h3><p>I knew about the light show at the Gardens by the Bay and I had planned to go there tonight. So, it was a delight for me that <a href="https://www.linkedin.com/in/arianna-capizzi">Arianna Capizzi</a> of ChatGDG announced that there would be a group of people heading to the same destination. Awesome let's do it!</p><p>If I recall correctly, we were roughly twelve to thirteen people - the Dirty Dozen figuratively speaking - that met down at the lobby of the hotel and hauled a few Grab drivers to get to the Gardens. It was definitely quicker and more comfortable than using public transport and while sharing the cost also not so expensive after all.</p><p>With a selection of songs from various world-known musicals we enjoyed the light spectacle right in front of the <a href="https://maps.app.goo.gl/TjDd7KYKUxRy57cH7">Supertree Observatory</a> and under the Skywalk. It was enchanting to say at least, highly recommended. Meanwhile I animated <a href="https://www.linkedin.com/in/lisacarpenter/?lipi=urn%3Ali%3Apage%3Ad_flagship3_feed%3Bmv7ZhOayQ5mdxijTN7QtLg%3D%3D">Lisa Carpenter</a> to re-activate her account on <a href="https://www.ingress.com/">Ingress</a> and join me playing. We gladly explained to <a href="https://www.linkedin.com/in/monika-janota/?lipi=urn%3Ali%3Apage%3Ad_flagship3_feed%3Bmv7ZhOayQ5mdxijTN7QtLg%3D%3D">Monika Janota</a> the purpose and the mechanics of the game. There is a crazy amount of portals all over Singapore.</p><p>As the hunger kicked in slowly but surely we decided to head over to the hawker centre in the Marina Sands Bay. Taking the Marina Bay Overpass we crossed the Dragonfly Lake and went straight into The Shoppes at Marina Sands Bay. Down the escalators and then the long straight to the food court.</p><p>Finding enough seats for such a big group at this time seems very challenging. And so unfortunately we had to split into smaller units, chope'd our places and went off exploring the different stalls sourcing for food. There is an incredible variety of dishes available.</p><figure class="kg-card kg-gallery-card kg-width-wide"><div class="kg-gallery-container"><div class="kg-gallery-row"><div class="kg-gallery-image"><img src="https://jochen.kirstaetter.name/content/images/2024/01/PXL_20240126_115852680.jpg" width="960" height="720" alt="Developer Creators and Online Communities Summit" srcset="https://jochen.kirstaetter.name/content/images/size/w600/2024/01/PXL_20240126_115852680.jpg 600w, https://jochen.kirstaetter.name/content/images/2024/01/PXL_20240126_115852680.jpg 960w" sizes="(min-width: 720px) 720px"></div><div class="kg-gallery-image"><img src="https://jochen.kirstaetter.name/content/images/2024/01/PXL_20240126_120637129.jpg" width="960" height="720" alt="Developer Creators and Online Communities Summit" srcset="https://jochen.kirstaetter.name/content/images/size/w600/2024/01/PXL_20240126_120637129.jpg 600w, https://jochen.kirstaetter.name/content/images/2024/01/PXL_20240126_120637129.jpg 960w" sizes="(min-width: 720px) 720px"></div><div class="kg-gallery-image"><img src="https://jochen.kirstaetter.name/content/images/2024/01/PXL_20240126_121343185.jpg" width="960" height="720" alt="Developer Creators and Online Communities Summit" srcset="https://jochen.kirstaetter.name/content/images/size/w600/2024/01/PXL_20240126_121343185.jpg 600w, https://jochen.kirstaetter.name/content/images/2024/01/PXL_20240126_121343185.jpg 960w" sizes="(min-width: 720px) 720px"></div></div><div class="kg-gallery-row"><div class="kg-gallery-image"><img src="https://jochen.kirstaetter.name/content/images/2024/01/PXL_20240126_122638029.jpg" width="960" height="720" alt="Developer Creators and Online Communities Summit" srcset="https://jochen.kirstaetter.name/content/images/size/w600/2024/01/PXL_20240126_122638029.jpg 600w, https://jochen.kirstaetter.name/content/images/2024/01/PXL_20240126_122638029.jpg 960w" sizes="(min-width: 720px) 720px"></div><div class="kg-gallery-image"><img src="https://jochen.kirstaetter.name/content/images/2024/01/PXL_20240126_140807246.jpg" width="960" height="540" alt="Developer Creators and Online Communities Summit" srcset="https://jochen.kirstaetter.name/content/images/size/w600/2024/01/PXL_20240126_140807246.jpg 600w, https://jochen.kirstaetter.name/content/images/2024/01/PXL_20240126_140807246.jpg 960w" sizes="(min-width: 720px) 720px"></div><div class="kg-gallery-image"><img src="https://jochen.kirstaetter.name/content/images/2024/01/PXL_20240126_145419126.jpg" width="960" height="720" alt="Developer Creators and Online Communities Summit" srcset="https://jochen.kirstaetter.name/content/images/size/w600/2024/01/PXL_20240126_145419126.jpg 600w, https://jochen.kirstaetter.name/content/images/2024/01/PXL_20240126_145419126.jpg 960w" sizes="(min-width: 720px) 720px"></div></div><div class="kg-gallery-row"><div class="kg-gallery-image"><img src="https://jochen.kirstaetter.name/content/images/2024/01/PXL_20240126_141928466.jpg" width="960" height="720" alt="Developer Creators and Online Communities Summit" srcset="https://jochen.kirstaetter.name/content/images/size/w600/2024/01/PXL_20240126_141928466.jpg 600w, https://jochen.kirstaetter.name/content/images/2024/01/PXL_20240126_141928466.jpg 960w" sizes="(min-width: 720px) 720px"></div><div class="kg-gallery-image"><img src="https://jochen.kirstaetter.name/content/images/2024/01/PXL_20240126_163101042.MP--1-.jpg" width="960" height="455" alt="Developer Creators and Online Communities Summit" srcset="https://jochen.kirstaetter.name/content/images/size/w600/2024/01/PXL_20240126_163101042.MP--1-.jpg 600w, https://jochen.kirstaetter.name/content/images/2024/01/PXL_20240126_163101042.MP--1-.jpg 960w" sizes="(min-width: 720px) 720px"></div><div class="kg-gallery-image"><img src="https://jochen.kirstaetter.name/content/images/2024/01/PXL_20240126_163319430.jpg" width="960" height="720" alt="Developer Creators and Online Communities Summit" srcset="https://jochen.kirstaetter.name/content/images/size/w600/2024/01/PXL_20240126_163319430.jpg 600w, https://jochen.kirstaetter.name/content/images/2024/01/PXL_20240126_163319430.jpg 960w" sizes="(min-width: 720px) 720px"></div></div></div></figure><p>After we concluded our culinary adventures we headed to the Waterfront Promenade and attended the <a href="https://maps.app.goo.gl/ihDs8Z66CtjUFahe7">Spectra - A Light &amp; Water Show</a>. What a joy for eyes and ears.</p><p>Later on we strolled down the Waterfront Promenade fully indulged in conversations of all kind of sorts, and marvelled together at the night skyline of Singapore. With all the talking we needed some drinks and therefore stopped by one the pubs in the surrounding. Before returning back to the hotel, we managed to visit <a href="https://maps.app.goo.gl/ASywfY9noB616Ed39">Lau Pa Sat</a>, the "old market" and first hawker centre in Singapore.</p><p>What a remarkable day full of sharing community experience, learning, exchanging, networking, conversing, dining, and fun it was.</p><h2 id="day-4">Day 4</h2><p>Exploration time, again!</p><p>As my flight back home was scheduled for the evening, I decided to spend my last day in Singapore (for now) in Chinatown, again. Like previously, I checked out of the hotel first thing in the morning but also asked the concierge desk to store my luggage until the afternoon.</p><h3 id="shop-until-you-drop-chinese-new-year-cny-">Shop until you drop: Chinese New Year (CNY)</h3><p>Starting at the People's Park Complex mall I explored the street market in Chinatown, went to the Chinatown Complex, then back to Pagoda Street where I found a nice place to have lunch. As I was looking for something specific I went across the overpass back into the People's Park Centre discovering all kind of items at the Night Bazaar. And after checking out all levels inside Chinatown Point mall I was finally done.</p><p>Unsurprisingly I had to buy another backpack (50l volume) to fit in all the items purchased. Given this half-day shopping spree I am not so sure about organising a (one week) vacation with the family here in Singapore is such a good idea. Especially around the time of Chinese New Year. Just kidding!</p><figure class="kg-card kg-gallery-card kg-width-wide"><div class="kg-gallery-container"><div class="kg-gallery-row"><div class="kg-gallery-image"><img src="https://jochen.kirstaetter.name/content/images/2024/01/PXL_20240127_063034017.MP.jpg" width="960" height="720" alt="Developer Creators and Online Communities Summit" srcset="https://jochen.kirstaetter.name/content/images/size/w600/2024/01/PXL_20240127_063034017.MP.jpg 600w, https://jochen.kirstaetter.name/content/images/2024/01/PXL_20240127_063034017.MP.jpg 960w" sizes="(min-width: 720px) 720px"></div><div class="kg-gallery-image"><img src="https://jochen.kirstaetter.name/content/images/2024/01/PXL_20240127_074141192.jpg" width="960" height="720" alt="Developer Creators and Online Communities Summit" srcset="https://jochen.kirstaetter.name/content/images/size/w600/2024/01/PXL_20240127_074141192.jpg 600w, https://jochen.kirstaetter.name/content/images/2024/01/PXL_20240127_074141192.jpg 960w" sizes="(min-width: 720px) 720px"></div><div class="kg-gallery-image"><img src="https://jochen.kirstaetter.name/content/images/2024/01/PXL_20240127_071904331.jpg" width="960" height="720" alt="Developer Creators and Online Communities Summit" srcset="https://jochen.kirstaetter.name/content/images/size/w600/2024/01/PXL_20240127_071904331.jpg 600w, https://jochen.kirstaetter.name/content/images/2024/01/PXL_20240127_071904331.jpg 960w" sizes="(min-width: 720px) 720px"></div></div><div class="kg-gallery-row"><div class="kg-gallery-image"><img src="https://jochen.kirstaetter.name/content/images/2024/01/PXL_20240127_064044562.jpg" width="960" height="720" alt="Developer Creators and Online Communities Summit" srcset="https://jochen.kirstaetter.name/content/images/size/w600/2024/01/PXL_20240127_064044562.jpg 600w, https://jochen.kirstaetter.name/content/images/2024/01/PXL_20240127_064044562.jpg 960w" sizes="(min-width: 720px) 720px"></div><div class="kg-gallery-image"><img src="https://jochen.kirstaetter.name/content/images/2024/01/PXL_20240127_065142448.jpg" width="960" height="589" alt="Developer Creators and Online Communities Summit" srcset="https://jochen.kirstaetter.name/content/images/size/w600/2024/01/PXL_20240127_065142448.jpg 600w, https://jochen.kirstaetter.name/content/images/2024/01/PXL_20240127_065142448.jpg 960w" sizes="(min-width: 720px) 720px"></div><div class="kg-gallery-image"><img src="https://jochen.kirstaetter.name/content/images/2024/01/PXL_20240127_063910135.jpg" width="960" height="774" alt="Developer Creators and Online Communities Summit" srcset="https://jochen.kirstaetter.name/content/images/size/w600/2024/01/PXL_20240127_063910135.jpg 600w, https://jochen.kirstaetter.name/content/images/2024/01/PXL_20240127_063910135.jpg 960w" sizes="(min-width: 720px) 720px"></div></div></div></figure><h3 id="see-you-soon-">See you soon!</h3><p>Reflecting over those past few days in Singapore while writing this blog recalled numerous conversations I had with other participants. I was excited meeting my community friends from the SSA region, finally being able to associate a face and person to the countless peers from the <a href="https://discord.gg/google-dev-community" rel="noopener">Google Developer Community</a> Discord server, and massively enjoying the amount of new contacts made. Hooray to LinkedIn's QR Code feature which smoothlessly allowed all us to foster that new acquaintance on social media.</p><p>I don't know about others, but looking at my photos collection I have close to 600 pictures taken. Singapore by day, Singapore by night, during the presentations at the Summit, and a couple of selfies with like-minded community folks. For the next few weeks I'm going to sieve through everything recorded and noted down, going to deepen those newly established connections, and looking forward to apply other creator's experience to my content creation process. Whether it will be more blog articles or fresh podcast episodes.</p><p>To each and every one I met during the DCOC Summit: <br><strong>You're incredible and thank you for spending some time with me. I appreciate you.</strong> 🫶</p><p>For now it's Goodbye community, goodbye Singapore, see you soon.</p><h2 id="shout-out-to-the-organising-team">Shout out to the organising team</h2><p>My heartfelt thanks go to <a href="https://www.linkedin.com/in/dirkprimbs/">Dirk Primbs</a>, <a href="https://www.linkedin.com/in/alicja-heisig-chiarello/">Alicja Heisig-Chiarello</a>, <a href="https://www.linkedin.com/in/alepalmieri/">Alessandro Palmieri</a>, <a href="https://www.linkedin.com/in/monika-janota/">Monika Janota</a>, <a href="https://www.linkedin.com/in/alfredomorresi/">Alfredo Morresi</a>, <a href="https://www.linkedin.com/in/nathalie-pereira-063a513/">Nathalie Pereira</a> and the rest of the team at Google for organising such an amazing summit and bringing Developer Creators and organisers of Online Communities world-wide together in one place.</p><p><strong>Thank You!</strong></p><p>What a remarkable, first Developer Creators and Online Communities Summit it was. Well done!</p><!--kg-card-begin: html--><small>Image credits: Own snaphots and pictures taken by other creators and shared in an album on Google Photos.</small><!--kg-card-end: html-->]]></content:encoded></item><item><title><![CDATA[DevFest Jinja 2023]]></title><description><![CDATA[First time travelling to Uganda and speaking at DevFest Jinja. It was a bit of a roller coaster however wonderful experience in total. With the highlight being a visit to the Source of the Nile.]]></description><link>https://jochen.kirstaetter.name/devfest-jinja-2023/</link><guid isPermaLink="false">655e526c560f497527123ef2</guid><category><![CDATA[Community]]></category><dc:creator><![CDATA[Jochen Kirstätter]]></dc:creator><pubDate>Thu, 28 Dec 2023 17:00:00 GMT</pubDate><media:content url="https://jochen.kirstaetter.name/content/images/2023/11/F_yN7y4WgAA77fN.jpeg" medium="image"/><content:encoded><![CDATA[<img src="https://jochen.kirstaetter.name/content/images/2023/11/F_yN7y4WgAA77fN.jpeg" alt="DevFest Jinja 2023"><p>Uganda - a new destination to explore. My first time travelling to Uganda and it is for speaking at DevFest Jinja. Following the conversations with <a href="https://www.linkedin.com/in/francis-akol/">Francis Akol</a> we arranged and got it approved that I would be able to travel as Google Developer Expert (GDE). A first for GDG Jinja.</p><p>During several past occasions I met Francis, <a href="https://www.linkedin.com/in/fiona-nangobi/">Fiona Nangobi</a> (WTM ambassador in Jinja), and other community members from Uganda. Meaning, taking the trip to Jinja wouldn't be an adventure into the complete unknown but a welcoming experience with friends.</p><p>In preparation I had the <a href="https://immigration.go.ug/services/east-african-tourist-visa">East Africa(n) Tourist Visa</a> (EATV) in my passport which would fast-track me at the immigration officer, or at least that's what I thought would be the case; more on that below, I found valuable resources online which described where the ATMs would be located in the airport, and where to purchase a Ugandan SIM card. I chose Airtel due to recommendations regarding network coverage and quality.</p><p>Like for my trip to Dar es Salaam two weeks ago, I decided to fly one or two earlier so that there be a chance for a bit of sightseeing. However this meant to be at the airport in the middle of the night, around 2:00 hrs in the morning catching the flight at 4:00 hrs then. As usual, the trip involved a stopover of approximately seven hours in Nairobi. While waiting in the Pride of Africa lounge I also seized the opportunity to clear a few issues I was facing with <a href="https://asante.kenya-airways.com/">Asante Rewards</a>, the frequent flyer loyalty program by Kenya Airways.</p><h2 id="to-enter-or-not-to-enter">To enter, or Not to enter</h2><p>that is the question: <br>Whether 'tis nobler in the mind to suffer<br>The slings and arrows of outrageous fortune,<br>Or to take Arms against a Sea of troubles,<br><a href="https://en.wikipedia.org/wiki/To_be,_or_not_to_be">...</a></p><p>It was not as dramatic as the opening speech of Prince Hamlet, however it was challenging nevertheless. Already back in Mauritius I was questioned about whether I had a VISA to enter Uganda, and again in Nairobi prior to boarding, I was quite surprised when I was told by the immigration officer that the EATV has expired. Hmm, hang on, I applied for it beginning of October and it's valid for 90 days, given multiple entry in either Rwanda, Kenya, or Uganda - so I thought.</p><p>Well, there is an important detail which can be overseen quite easily or misunderstood as in my case. </p><blockquote>The visa is valid for 90 days and is not renewable upon expiry or upon exit from the block (Kenya, Uganda, Rwanda).</blockquote><p>The East Africa Tourist Visa (EATV) is an agreement between those three mentioned countries to ease transits between them for the given period. However the visa itself is single entry coming from any other country and (!) it expires as soon as you exit the defined realm. </p><p><strong><em>Ouch!</em></strong> <br>I totally didn't see that back in October and it wasn't mentioned by the immigration officer in Kigali, Rwanda. Either way it was my fault or at least responsibility. With all the forth and back between immigration officer at the counter, direct supervisor, moving to the immigration offices at the back, and then speaking to the head supervisor about the situation, it crossed my mind that this could be a potential episode of Border Security.</p><p>This is Africa, and there is always a way. Given my passport of European origin I was offered to apply for a new visa on arrival. Which I gratefully accepted. I mean paying USD $50 for my misunderstanding, read: the visa to enter Uganda, is a fair deal after all. Definitely better than sitting on the next plane back home.</p><h2 id="let-the-real-adventure-begin">Let the real adventure begin</h2><p>After withdrawing some cash from one of the ATM and purchasing the Airtel SIM card I was ready for my first experience in Uganda. And what better to receive a hearty welcome by GDG fellow <a href="https://twitter.com/AsaLugada">Asa Lugada</a> and his friend Arnold. My connection to Asa even goes back to my first participation in the Andela-led ALC program, later GADS program. And of course the <a href="https://jochen.kirstaetter.name/ssa-community-summit-2018/">SSA Community Summit 2018</a>.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://jochen.kirstaetter.name/content/images/2024/01/PXL_20231123_133809384.MP.jpg" class="kg-image" alt="DevFest Jinja 2023" srcset="https://jochen.kirstaetter.name/content/images/size/w600/2024/01/PXL_20231123_133809384.MP.jpg 600w, https://jochen.kirstaetter.name/content/images/size/w1000/2024/01/PXL_20231123_133809384.MP.jpg 1000w, https://jochen.kirstaetter.name/content/images/2024/01/PXL_20231123_133809384.MP.jpg 1280w" sizes="(min-width: 720px) 720px"><figcaption>Welcoming committee at the airport of Entebbe, Uganda</figcaption></figure><p>Some days earlier we discussed details about the airport transfer to the guest house I'm staying in Jinja. Of course, I could have a booked a taxi or an arrangement with the guest house but this premium community service was by far the better option.</p><p>From Entebbe to Jinja is roughly 130km to drive. So we stopped at the Victoria Mall in Entebbe, got ourselves some snacks and refreshments, and off we went...</p><figure class="kg-card kg-gallery-card kg-width-wide"><div class="kg-gallery-container"><div class="kg-gallery-row"><div class="kg-gallery-image"><img src="https://jochen.kirstaetter.name/content/images/2024/01/PXL_20231123_141445934.jpg" width="960" height="1223" alt="DevFest Jinja 2023" srcset="https://jochen.kirstaetter.name/content/images/size/w600/2024/01/PXL_20231123_141445934.jpg 600w, https://jochen.kirstaetter.name/content/images/2024/01/PXL_20231123_141445934.jpg 960w" sizes="(min-width: 720px) 720px"></div><div class="kg-gallery-image"><img src="https://jochen.kirstaetter.name/content/images/2024/01/PXL_20231123_141450189.jpg" width="960" height="903" alt="DevFest Jinja 2023" srcset="https://jochen.kirstaetter.name/content/images/size/w600/2024/01/PXL_20231123_141450189.jpg 600w, https://jochen.kirstaetter.name/content/images/2024/01/PXL_20231123_141450189.jpg 960w" sizes="(min-width: 720px) 720px"></div><div class="kg-gallery-image"><img src="https://jochen.kirstaetter.name/content/images/2024/01/PXL_20231123_143634637.jpg" width="960" height="371" alt="DevFest Jinja 2023" srcset="https://jochen.kirstaetter.name/content/images/size/w600/2024/01/PXL_20231123_143634637.jpg 600w, https://jochen.kirstaetter.name/content/images/2024/01/PXL_20231123_143634637.jpg 960w" sizes="(min-width: 720px) 720px"></div></div><div class="kg-gallery-row"><div class="kg-gallery-image"><img src="https://jochen.kirstaetter.name/content/images/2024/01/PXL_20231123_152924578.jpg" width="960" height="538" alt="DevFest Jinja 2023" srcset="https://jochen.kirstaetter.name/content/images/size/w600/2024/01/PXL_20231123_152924578.jpg 600w, https://jochen.kirstaetter.name/content/images/2024/01/PXL_20231123_152924578.jpg 960w" sizes="(min-width: 720px) 720px"></div><div class="kg-gallery-image"><img src="https://jochen.kirstaetter.name/content/images/2024/01/PXL_20231123_152657321.jpg" width="960" height="540" alt="DevFest Jinja 2023" srcset="https://jochen.kirstaetter.name/content/images/size/w600/2024/01/PXL_20231123_152657321.jpg 600w, https://jochen.kirstaetter.name/content/images/2024/01/PXL_20231123_152657321.jpg 960w" sizes="(min-width: 720px) 720px"></div><div class="kg-gallery-image"><img src="https://jochen.kirstaetter.name/content/images/2024/01/PXL_20231123_151235321.MP.jpg" width="960" height="474" alt="DevFest Jinja 2023" srcset="https://jochen.kirstaetter.name/content/images/size/w600/2024/01/PXL_20231123_151235321.MP.jpg 600w, https://jochen.kirstaetter.name/content/images/2024/01/PXL_20231123_151235321.MP.jpg 960w" sizes="(min-width: 720px) 720px"></div></div><div class="kg-gallery-row"><div class="kg-gallery-image"><img src="https://jochen.kirstaetter.name/content/images/2024/01/PXL_20231123_152825558.jpg" width="960" height="511" alt="DevFest Jinja 2023" srcset="https://jochen.kirstaetter.name/content/images/size/w600/2024/01/PXL_20231123_152825558.jpg 600w, https://jochen.kirstaetter.name/content/images/2024/01/PXL_20231123_152825558.jpg 960w" sizes="(min-width: 720px) 720px"></div><div class="kg-gallery-image"><img src="https://jochen.kirstaetter.name/content/images/2024/01/PXL_20231123_152602334.jpg" width="960" height="477" alt="DevFest Jinja 2023" srcset="https://jochen.kirstaetter.name/content/images/size/w600/2024/01/PXL_20231123_152602334.jpg 600w, https://jochen.kirstaetter.name/content/images/2024/01/PXL_20231123_152602334.jpg 960w" sizes="(min-width: 720px) 720px"></div></div></div></figure><p>Giving or taking it took us approximately five hours to the guesthouse in Jinja. Thanks to Google Maps we managed to find the place straight away. After check-in and inspection of the room we headed to a nearby Indian-Asian restaurant and we treated ourselves with some tasty delights. Later on I could finally enjoy a well-deserved shower and rest in bed. It was an exciting but also tiring day of travelling. </p><h2 id="source-of-the-nile">Source of the Nile</h2><p>Arriving at least a day in advance has some advantages than just being there for the DevFest. I've seen this already with GDEs that came to speak at DevFest Mauritius, and I've done it travelling to <a href="https://jochen.kirstaetter.name/devfest-dar-es-salaam-2023/">DevFest Dar es Salaam</a> previously.</p><figure class="kg-card kg-image-card kg-width-full kg-card-hascaption"><img src="https://jochen.kirstaetter.name/content/images/2024/01/PXL_20231124_114607489.PANO-1.jpg" class="kg-image" alt="DevFest Jinja 2023" srcset="https://jochen.kirstaetter.name/content/images/size/w600/2024/01/PXL_20231124_114607489.PANO-1.jpg 600w, https://jochen.kirstaetter.name/content/images/size/w1000/2024/01/PXL_20231124_114607489.PANO-1.jpg 1000w, https://jochen.kirstaetter.name/content/images/2024/01/PXL_20231124_114607489.PANO-1.jpg 1440w"><figcaption>Heading out onto Lake Victoria... well that's a very tiny sidearm only</figcaption></figure><p>Francis suggested to meet first at my place, so that Marvin and Cynthia could deposit their stuff in my room, then a quick check of the venue and then seeing what we could do for the rest of the day. Weeks ago I mentioned that I would like to explore the source of the Nile which isn't too far from my local guesthouse anyways.</p><figure class="kg-card kg-gallery-card kg-width-wide kg-card-hascaption"><div class="kg-gallery-container"><div class="kg-gallery-row"><div class="kg-gallery-image"><img src="https://jochen.kirstaetter.name/content/images/2024/01/20231124_135407.jpg" width="960" height="480" alt="DevFest Jinja 2023" srcset="https://jochen.kirstaetter.name/content/images/size/w600/2024/01/20231124_135407.jpg 600w, https://jochen.kirstaetter.name/content/images/2024/01/20231124_135407.jpg 960w" sizes="(min-width: 720px) 720px"></div><div class="kg-gallery-image"><img src="https://jochen.kirstaetter.name/content/images/2024/01/PXL_20231124_115738000.jpg" width="960" height="389" alt="DevFest Jinja 2023" srcset="https://jochen.kirstaetter.name/content/images/size/w600/2024/01/PXL_20231124_115738000.jpg 600w, https://jochen.kirstaetter.name/content/images/2024/01/PXL_20231124_115738000.jpg 960w" sizes="(min-width: 720px) 720px"></div><div class="kg-gallery-image"><img src="https://jochen.kirstaetter.name/content/images/2024/01/PXL_20231124_115811615.jpg" width="960" height="530" alt="DevFest Jinja 2023" srcset="https://jochen.kirstaetter.name/content/images/size/w600/2024/01/PXL_20231124_115811615.jpg 600w, https://jochen.kirstaetter.name/content/images/2024/01/PXL_20231124_115811615.jpg 960w" sizes="(min-width: 720px) 720px"></div></div><div class="kg-gallery-row"><div class="kg-gallery-image"><img src="https://jochen.kirstaetter.name/content/images/2024/01/20231124_135455.jpg" width="960" height="456" alt="DevFest Jinja 2023" srcset="https://jochen.kirstaetter.name/content/images/size/w600/2024/01/20231124_135455.jpg 600w, https://jochen.kirstaetter.name/content/images/2024/01/20231124_135455.jpg 960w" sizes="(min-width: 720px) 720px"></div><div class="kg-gallery-image"><img src="https://jochen.kirstaetter.name/content/images/2024/01/PXL_20231124_114607489.PANO.jpg" width="2000" height="496" alt="DevFest Jinja 2023" srcset="https://jochen.kirstaetter.name/content/images/size/w600/2024/01/PXL_20231124_114607489.PANO.jpg 600w, https://jochen.kirstaetter.name/content/images/size/w1000/2024/01/PXL_20231124_114607489.PANO.jpg 1000w, https://jochen.kirstaetter.name/content/images/size/w1600/2024/01/PXL_20231124_114607489.PANO.jpg 1600w, https://jochen.kirstaetter.name/content/images/size/w2400/2024/01/PXL_20231124_114607489.PANO.jpg 2400w" sizes="(min-width: 720px) 720px"></div><div class="kg-gallery-image"><img src="https://jochen.kirstaetter.name/content/images/2024/01/original_a79ab622-ef85-4c14-959b-ef84fa4615a4_PXL_20231124_113428410.jpg" width="960" height="675" alt="DevFest Jinja 2023" srcset="https://jochen.kirstaetter.name/content/images/size/w600/2024/01/original_a79ab622-ef85-4c14-959b-ef84fa4615a4_PXL_20231124_113428410.jpg 600w, https://jochen.kirstaetter.name/content/images/2024/01/original_a79ab622-ef85-4c14-959b-ef84fa4615a4_PXL_20231124_113428410.jpg 960w" sizes="(min-width: 720px) 720px"></div></div><div class="kg-gallery-row"><div class="kg-gallery-image"><img src="https://jochen.kirstaetter.name/content/images/2024/01/PXL_20231124_111032930.jpg" width="960" height="422" alt="DevFest Jinja 2023" srcset="https://jochen.kirstaetter.name/content/images/size/w600/2024/01/PXL_20231124_111032930.jpg 600w, https://jochen.kirstaetter.name/content/images/2024/01/PXL_20231124_111032930.jpg 960w" sizes="(min-width: 720px) 720px"></div><div class="kg-gallery-image"><img src="https://jochen.kirstaetter.name/content/images/2024/01/20231124_141643.jpg" width="960" height="475" alt="DevFest Jinja 2023" srcset="https://jochen.kirstaetter.name/content/images/size/w600/2024/01/20231124_141643.jpg 600w, https://jochen.kirstaetter.name/content/images/2024/01/20231124_141643.jpg 960w" sizes="(min-width: 720px) 720px"></div><div class="kg-gallery-image"><img src="https://jochen.kirstaetter.name/content/images/2024/01/20231124_135804.jpg" width="960" height="329" alt="DevFest Jinja 2023" srcset="https://jochen.kirstaetter.name/content/images/size/w600/2024/01/20231124_135804.jpg 600w, https://jochen.kirstaetter.name/content/images/2024/01/20231124_135804.jpg 960w" sizes="(min-width: 720px) 720px"></div></div></div><figcaption>Taking the boat tour to the Source of the Nile was rewarding by nature. Did you spot the Monitor Lizard?</figcaption></figure><p>It was an amazing excursion and learning that ashes of the late Mahatma Gandhi have been spread out here at source was an interesting note. </p><figure class="kg-card kg-gallery-card kg-width-wide kg-card-hascaption"><div class="kg-gallery-container"><div class="kg-gallery-row"><div class="kg-gallery-image"><img src="https://jochen.kirstaetter.name/content/images/2024/01/20231124_135055.jpg" width="960" height="611" alt="DevFest Jinja 2023" srcset="https://jochen.kirstaetter.name/content/images/size/w600/2024/01/20231124_135055.jpg 600w, https://jochen.kirstaetter.name/content/images/2024/01/20231124_135055.jpg 960w" sizes="(min-width: 720px) 720px"></div><div class="kg-gallery-image"><img src="https://jochen.kirstaetter.name/content/images/2024/01/PXL_20231124_103701468.jpg" width="960" height="1404" alt="DevFest Jinja 2023" srcset="https://jochen.kirstaetter.name/content/images/size/w600/2024/01/PXL_20231124_103701468.jpg 600w, https://jochen.kirstaetter.name/content/images/2024/01/PXL_20231124_103701468.jpg 960w" sizes="(min-width: 720px) 720px"></div></div><div class="kg-gallery-row"><div class="kg-gallery-image"><img src="https://jochen.kirstaetter.name/content/images/2024/01/PXL_20231124_100911840-EFFECTS.jpg" width="960" height="612" alt="DevFest Jinja 2023" srcset="https://jochen.kirstaetter.name/content/images/size/w600/2024/01/PXL_20231124_100911840-EFFECTS.jpg 600w, https://jochen.kirstaetter.name/content/images/2024/01/PXL_20231124_100911840-EFFECTS.jpg 960w" sizes="(min-width: 720px) 720px"></div><div class="kg-gallery-image"><img src="https://jochen.kirstaetter.name/content/images/2024/01/PXL_20231124_103004700.jpg" width="960" height="920" alt="DevFest Jinja 2023" srcset="https://jochen.kirstaetter.name/content/images/size/w600/2024/01/PXL_20231124_103004700.jpg 600w, https://jochen.kirstaetter.name/content/images/2024/01/PXL_20231124_103004700.jpg 960w" sizes="(min-width: 720px) 720px"></div></div></div><figcaption>Spiritual experience near the source</figcaption></figure><p>I had a great day, good company and delicious food. Highly recommended!</p><h2 id="devfest-jinja">DevFest Jinja</h2><p>After getting some hours of sleep the big day had finally arrived. I enjoyed a nice local breakfast - called Rolex - and then called for a boda to get to <a href="https://innovationvillage.africa/">The Innovation Village</a> for DevFest Jinja.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://jochen.kirstaetter.name/content/images/2024/01/20231125_081353.jpg" class="kg-image" alt="DevFest Jinja 2023" srcset="https://jochen.kirstaetter.name/content/images/size/w600/2024/01/20231125_081353.jpg 600w, https://jochen.kirstaetter.name/content/images/2024/01/20231125_081353.jpg 960w" sizes="(min-width: 720px) 720px"><figcaption>Rolex - another local speciality not to miss</figcaption></figure><p>It was clearly way too early when I arrived at the venue. But well, better too early than too late, and therefore I took some time to talk to other GDG organisers, spoke to Fiona Nangobi, and was chit-chatting with Marvin and Cynthia about yesterday's excursion and other highlights.</p><p>More and more people arrived and so Francis kicked off DevFest Jinja with a respectable crowd. A few minutes in the reception and registration area was swarmed with WTM ladies, already in their gowns for the dinner arrangement later that day. It was an amazing display of vibrant colours, great happiness and big smiles on the faces of all attendees.</p><p>I was scheduled with two sessions. During the first half of the day, I spoke about the benefits of .NET and how implementations in C# as well as ASP.NET can be developed swiftly and deployed easily to various services offered by Google Cloud Platform. There were numerous questions about use cases of C# and how the available Google APIs can be accessed via NuGet packages. </p><p>In the afternoon session I talked about the importance and advantages of professional certifications, in particular given the survey results that Google Cloud certifications are ranked among the highest paid ones. Build up your expertise and prove to yourself and others that you know your subject and that you are a knowledgable Google Cloud engineer. Those certification can open doors to higher payment on the job, better job offers and potentially a chance to work remotely with companies abroad.</p><figure class="kg-card kg-gallery-card kg-width-wide kg-card-hascaption"><div class="kg-gallery-container"><div class="kg-gallery-row"><div class="kg-gallery-image"><img src="https://jochen.kirstaetter.name/content/images/2024/01/PXL_20231124_075400430.jpg" width="960" height="1233" alt="DevFest Jinja 2023" srcset="https://jochen.kirstaetter.name/content/images/size/w600/2024/01/PXL_20231124_075400430.jpg 600w, https://jochen.kirstaetter.name/content/images/2024/01/PXL_20231124_075400430.jpg 960w" sizes="(min-width: 720px) 720px"></div><div class="kg-gallery-image"><img src="https://jochen.kirstaetter.name/content/images/2024/01/PXL_20231125_074608446.MP.jpg" width="960" height="460" alt="DevFest Jinja 2023" srcset="https://jochen.kirstaetter.name/content/images/size/w600/2024/01/PXL_20231125_074608446.MP.jpg 600w, https://jochen.kirstaetter.name/content/images/2024/01/PXL_20231125_074608446.MP.jpg 960w" sizes="(min-width: 720px) 720px"></div><div class="kg-gallery-image"><img src="https://jochen.kirstaetter.name/content/images/2024/01/PXL_20231125_080335623.jpg" width="960" height="409" alt="DevFest Jinja 2023" srcset="https://jochen.kirstaetter.name/content/images/size/w600/2024/01/PXL_20231125_080335623.jpg 600w, https://jochen.kirstaetter.name/content/images/2024/01/PXL_20231125_080335623.jpg 960w" sizes="(min-width: 720px) 720px"></div></div><div class="kg-gallery-row"><div class="kg-gallery-image"><img src="https://jochen.kirstaetter.name/content/images/2024/01/PXL_20231125_104639946.MP.jpg" width="960" height="520" alt="DevFest Jinja 2023" srcset="https://jochen.kirstaetter.name/content/images/size/w600/2024/01/PXL_20231125_104639946.MP.jpg 600w, https://jochen.kirstaetter.name/content/images/2024/01/PXL_20231125_104639946.MP.jpg 960w" sizes="(min-width: 720px) 720px"></div><div class="kg-gallery-image"><img src="https://jochen.kirstaetter.name/content/images/2024/01/20231125_170549.jpg" width="960" height="428" alt="DevFest Jinja 2023" srcset="https://jochen.kirstaetter.name/content/images/size/w600/2024/01/20231125_170549.jpg 600w, https://jochen.kirstaetter.name/content/images/2024/01/20231125_170549.jpg 960w" sizes="(min-width: 720px) 720px"></div><div class="kg-gallery-image"><img src="https://jochen.kirstaetter.name/content/images/2024/01/PXL_20231125_115259875.jpg" width="960" height="1323" alt="DevFest Jinja 2023" srcset="https://jochen.kirstaetter.name/content/images/size/w600/2024/01/PXL_20231125_115259875.jpg 600w, https://jochen.kirstaetter.name/content/images/2024/01/PXL_20231125_115259875.jpg 960w" sizes="(min-width: 720px) 720px"></div></div><div class="kg-gallery-row"><div class="kg-gallery-image"><img src="https://jochen.kirstaetter.name/content/images/2024/01/PXL_20231125_080314574.jpg" width="960" height="447" alt="DevFest Jinja 2023" srcset="https://jochen.kirstaetter.name/content/images/size/w600/2024/01/PXL_20231125_080314574.jpg 600w, https://jochen.kirstaetter.name/content/images/2024/01/PXL_20231125_080314574.jpg 960w" sizes="(min-width: 720px) 720px"></div><div class="kg-gallery-image"><img src="https://jochen.kirstaetter.name/content/images/2024/01/PXL_20231125_121208590.jpg" width="960" height="591" alt="DevFest Jinja 2023" srcset="https://jochen.kirstaetter.name/content/images/size/w600/2024/01/PXL_20231125_121208590.jpg 600w, https://jochen.kirstaetter.name/content/images/2024/01/PXL_20231125_121208590.jpg 960w" sizes="(min-width: 720px) 720px"></div></div></div><figcaption>Full house at DevFest Jinja</figcaption></figure><p>It was informative listening to the talks by other speakers. Feel free to check out the <a href="https://gdg.community.dev/events/details/google-gdg-jinja-presents-devfest-jinja-2023/">full agenda of DevFest Jinja</a> to see what you eventually missed.</p><p>With all those lovely people around, all the ongoing conversations and networking chats I somehow didn't realize that I had an exchange <a href="https://twitter.com/Rawahanector">Zirabamuzale Rawaha aka RumzTech</a>, organiser of GDG Luwero, with whom I did several remote sessions as part of the <a href="https://gdg.community.dev/events/details/google-gdg-luwero-presents-certification-study-group-associate-cloud-engineer-2023-05-27/">Road to Google Developers Certification</a> earlier this year. Mea culpa, Rawaha!</p><h2 id="ever-tasted-nsenene">Ever tasted Nsenene?</h2><p>Purely by chance Asa and I were standing outside on the pavement trying to get a bit of fresh air and having an interesting conversation when this guy with an orange bucket walked pass us. As I wasn't sure whether I saw correctly I asked Asa about the content of the bucket. "Ohh, you gotta taste this. Would you like to try?"</p><figure class="kg-card kg-gallery-card kg-width-wide"><div class="kg-gallery-container"><div class="kg-gallery-row"><div class="kg-gallery-image"><img src="https://jochen.kirstaetter.name/content/images/2024/01/PXL_20231125_115605702.jpg" width="960" height="720" alt="DevFest Jinja 2023" srcset="https://jochen.kirstaetter.name/content/images/size/w600/2024/01/PXL_20231125_115605702.jpg 600w, https://jochen.kirstaetter.name/content/images/2024/01/PXL_20231125_115605702.jpg 960w" sizes="(min-width: 720px) 720px"></div><div class="kg-gallery-image"><img src="https://jochen.kirstaetter.name/content/images/2024/01/PXL_20231125_115702504.jpg" width="960" height="1280" alt="DevFest Jinja 2023" srcset="https://jochen.kirstaetter.name/content/images/size/w600/2024/01/PXL_20231125_115702504.jpg 600w, https://jochen.kirstaetter.name/content/images/2024/01/PXL_20231125_115702504.jpg 960w" sizes="(min-width: 720px) 720px"></div><div class="kg-gallery-image"><img src="https://jochen.kirstaetter.name/content/images/2024/01/PXL_20231125_115810666-2.jpg" width="960" height="1280" alt="DevFest Jinja 2023" srcset="https://jochen.kirstaetter.name/content/images/size/w600/2024/01/PXL_20231125_115810666-2.jpg 600w, https://jochen.kirstaetter.name/content/images/2024/01/PXL_20231125_115810666-2.jpg 960w" sizes="(min-width: 720px) 720px"></div></div></div></figure><p>Yes, of course! Let's snack a handful roasted crickets - <a href="https://en.wikipedia.org/wiki/Nsenene">called nsenene in Luganda</a> - with small chopped white onions. This species is a delicacy in central and south-western Uganda. That's what I'm looking for while travelling other countries. Experiencing new flavours, new delicacies and new smells. And actually, those crickets are yummy. If you have a chance to taste... do it. You might be surprised.</p><h2 id="on-my-way-back-home">On my way back home</h2><p>Unfortunately, trips to speak at DevFest events are quite short, and so it was already time to say good bye. Thankfully Asa and Arnold offered to provide transfer to the airport, and we had to start quite early in the morning already. Shortly before driving through the Mabira Central Forest Reserve we were greeted by a massive weather spectacle with mesmerizing lightnings and roaring thunders. Whew, the streets turned into small streams and here and there we were joking about paddling in a kayak rather than driving in the car. We made it well ahead of departure time, and even managed to stop at the Victoria Mall again to have some breakfast with tea.</p><p>Another surprise was caused by Kenya Airways after we had landed in Nairobi. The scheduled flight to Mauritius had been delayed by another one and half hour so. Other travellers I met in the lounge were less lucky and were stranded for over twelve hours already. Eagerly hoping to continue their journeys.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://jochen.kirstaetter.name/content/images/2024/01/PXL_20231126_151837797.jpg" class="kg-image" alt="DevFest Jinja 2023" srcset="https://jochen.kirstaetter.name/content/images/size/w600/2024/01/PXL_20231126_151837797.jpg 600w, https://jochen.kirstaetter.name/content/images/2024/01/PXL_20231126_151837797.jpg 960w" sizes="(min-width: 720px) 720px"><figcaption>Arriving back during sunset - that's the west coast from Tamarin, Black River, Case Noyale down to Le Morne</figcaption></figure><h2 id="shout-out-to-gdg-jinja-and-wtm-jinja">Shout out to GDG Jinja and WTM Jinja</h2><p>Congratulations to such a wonderful DevFest. Thank you so much for the warm welcome, the overwhelming care-taking and the joy I have experienced during those few days in Uganda. I'm really happy about the new impressions and experiences made.</p><figure class="kg-card kg-image-card kg-width-wide"><img src="https://jochen.kirstaetter.name/content/images/2024/01/PXL_20231125_141329521.jpg" class="kg-image" alt="DevFest Jinja 2023" srcset="https://jochen.kirstaetter.name/content/images/size/w600/2024/01/PXL_20231125_141329521.jpg 600w, https://jochen.kirstaetter.name/content/images/2024/01/PXL_20231125_141329521.jpg 960w"></figure><p>Personal thanks to Francis Akol, Asa Lugada and Fiona Nangobi! Keep shining all of you!</p><p><em>Photo credits</em>: Shared album on Google Photos by GDG Jinja.</p>]]></content:encoded></item><item><title><![CDATA[Mau Pas Konpran!? Brain Drain]]></title><description><![CDATA[In our latest episode we - Loic, Ish and I - sat together and talked about the situation, possible reasons, and considerations regarding the emigration of Mauritians towards other countries and the potential impact on the society here on the island.]]></description><link>https://jochen.kirstaetter.name/mau-pas-konpran-2/</link><guid isPermaLink="false">6579f2f3f2f01b106a423499</guid><category><![CDATA[Podcast]]></category><category><![CDATA[Personal]]></category><category><![CDATA[Community]]></category><dc:creator><![CDATA[Jochen Kirstätter]]></dc:creator><pubDate>Tue, 19 Dec 2023 18:37:15 GMT</pubDate><media:content url="https://jochen.kirstaetter.name/content/images/2023/12/MauPasKonpran_20231213.jpg" medium="image"/><content:encoded><![CDATA[<img src="https://jochen.kirstaetter.name/content/images/2023/12/MauPasKonpran_20231213.jpg" alt="Mau Pas Konpran!? Brain Drain"><p>I don't understand!? - In our latest episode we - Loic, Ish and I - sat together and talked about the situation, possible reasons, and considerations regarding the emigration of Mauritians towards other countries and the potential impact on the society here on the island.</p><p>The so-called "brain drain" is happening since years and it kind of amazes me to see that people are looking for their chances and luck abroad when there are opportunities available in the country.</p><figure class="kg-card kg-image-card kg-width-wide kg-card-hascaption"><img src="https://jochen.kirstaetter.name/content/images/2023/12/Screenshot-from-2023-12-13-22-15-10.png" class="kg-image" alt="Mau Pas Konpran!? Brain Drain" srcset="https://jochen.kirstaetter.name/content/images/size/w600/2023/12/Screenshot-from-2023-12-13-22-15-10.png 600w, https://jochen.kirstaetter.name/content/images/size/w1000/2023/12/Screenshot-from-2023-12-13-22-15-10.png 1000w, https://jochen.kirstaetter.name/content/images/2023/12/Screenshot-from-2023-12-13-22-15-10.png 1280w" sizes="(min-width: 1200px) 1200px"><figcaption>A chilled evening session to discuss about the "brain drain" phenomena happening in Mauritius</figcaption></figure><blockquote>"The Grass is always greener on the other side."</blockquote><p>This proverb has the general understanding that life at other places is better than the current situation you are in. However this might be a superficial observation and there are other constraints playing into that, too.</p><p>Personally, I did the reverse. Meaning, I immigrated to Mauritius almost 17 years ago; initially as an expat on an Occupation Permit. And I have to admit that reaching certain goals and achievements would <strong>not</strong> have been possible back in Germany. Maybe possible but might have required much more effort, more time and more personal involvement. Who knows...</p><figure class="kg-card kg-embed-card kg-card-hascaption"><iframe style="border-radius: 12px" width="100%" height="152" title="Spotify Embed: Le gazon n&apos;est pas toujours plus vert ailleurs" frameborder="0" allowfullscreen allow="autoplay; clipboard-write; encrypted-media; fullscreen; picture-in-picture" loading="lazy" src="https://open.spotify.com/embed/episode/4reGdqWDI4FqbaCbJmBvKV?si=68e65a4ebee34677&utm_source=oembed"></iframe><figcaption>Mauritius and its brain drain - why is talent moving away?</figcaption></figure><p>Please, check out episode #2 of the Mau Pas Konpran podcast and let us know your thoughts on this particular topic. Maybe share your own experience in case you have moved away from your home country, and how you see it nowadays.</p><p>Thanks for reading and hopefully listening.</p><p>Joyeuses fêtes et BananE!</p><p>PS: We are considering to publish the podcast on Apple platform.</p>]]></content:encoded></item><item><title><![CDATA[DevFest Dar es Salaam 2023]]></title><description><![CDATA[With an improving health and running a few workshops - in-house and remote - earlier this year I was getting more and more eager as well excited about the idea to speak at DevFest Dar es Salaam, Tanzania.]]></description><link>https://jochen.kirstaetter.name/devfest-dar-es-salaam-2023/</link><guid isPermaLink="false">6551c5f2560f4975271239db</guid><category><![CDATA[Community]]></category><dc:creator><![CDATA[Jochen Kirstätter]]></dc:creator><pubDate>Tue, 12 Dec 2023 17:48:52 GMT</pubDate><media:content url="https://jochen.kirstaetter.name/content/images/2023/12/DX4A8685.jpg" medium="image"/><content:encoded><![CDATA[<img src="https://jochen.kirstaetter.name/content/images/2023/12/DX4A8685.jpg" alt="DevFest Dar es Salaam 2023"><p>After speaking at DevFest Nairobi in 2022 (including a spontaneous keynote on Google Cloud) I got inspired to be more active and hopefully present in other potential locations across the Sub-Saharan Africa region. And if I'm not completely wrong I also had an exchange with <a href="https://twitter.com/georgearwechu">Georgia Rwechungura</a> during the SSA Community Summit 2022 regarding the idea of coming to Tanzania, or more precisely to come to <a href="https://gdg.community.dev/gdg-dar-es-salaam/">GDG Dar es Salaam</a> and speaking at their DevFest.</p><p>With an improving health and running a few workshops - in-house and remote - earlier this year I was getting more and more eager as well as excited about the idea to speak at other DevFest events than <a href="https://jochen.kirstaetter.name/devfest-mauritius-2023/">Mauritius</a>. All went well at <a href="https://jochen.kirstaetter.name/devfest-kigali-2023/">DevFest Kigali</a> a few weeks earlier and so nothing could possibly stop me from going to Tanzania.</p><h2 id="getting-there-and-back">Getting there and back?</h2><p>Unfortunately, there are not many connections between Mauritius and African countries, or at least there could and should be many more than there are at the moment. Without a direct flight I had a look at the available options for airlines, airports and the associated stopover times. Here are a few routes I checked out:</p><ul><li>Johannesburg, South Africa</li><li>Nairobi, Kenya</li><li>Antananarivo, Madagascar</li><li>Dubai, UAE</li><li>Mahe, Seychelles</li><li>St. Denis, La Reunion</li></ul><p>It's really weird to travel in a yo-yo pattern like this. Meaning, you have to fly further than the actual destination and then "come back". A direct flight from Mauritius to Dar es Salaam would probably take less than three hours. Given the current possibilities it takes way more than twice the time. </p><p>Anyway, I chose to go with Kenya Airways and having a night stopover in Nairobi. With access to their Pride of Africa lounge it wasn't too bad after all.</p><h3 id="choice-of-accommodation">Choice of accommodation</h3><p>Usually I try to find a hotel or guesthouse that's close to the DevFest venue and doesn't have the flair of a typical business trip. Thanks to <a href="https://twitter.com/naaminiyonazi">Naamini Yonazi</a> I knew that DevFest would most likely be somewhere on the campus of the University of Dar es Salaam which lies North of the airport and the city centre. Traffic might be dense during morning hours and the suggestions provided on the GDE trip planning platform were too far away and most of them not to my liking.</p><p>Based on the positive experience I had with stays booked through the booking.com app in Europe I gave it a try for Tanzania. For those few days, I searched for an appropriate place to stay that is less than 30 minutes away from DevFest. Thanks to the ratings, great pictures, and other attributes like cost I actually found a hotel right on the beach. </p><figure class="kg-card kg-image-card kg-width-full kg-card-hascaption"><img src="https://jochen.kirstaetter.name/content/images/2023/12/PXL_20231110_145307298.PANO.jpg" class="kg-image" alt="DevFest Dar es Salaam 2023" srcset="https://jochen.kirstaetter.name/content/images/size/w600/2023/12/PXL_20231110_145307298.PANO.jpg 600w, https://jochen.kirstaetter.name/content/images/size/w1000/2023/12/PXL_20231110_145307298.PANO.jpg 1000w, https://jochen.kirstaetter.name/content/images/2023/12/PXL_20231110_145307298.PANO.jpg 1280w"><figcaption>Staying right at shores of the Indian Ocean - almost feels like home...</figcaption></figure><p>Surprisingly, it was also offered on the GDE trip planner but outside the suggested radius. With minor adjustments I got it as an option and was able to book without any issues. Winning!</p><h3 id="travel-companion">Travel companion</h3><p>Now, after seeing some pictures of the beach side, the pool, the rooms and the restaurants of the hotel my lovely BWE got very much interested in Tanzania. You might guess where this is heading to, don't you?</p><p>Following our wedding anniversary celebrations in September my BWE and I talked about the possibility to spend a long weekend together in Tanzania, and we decided that would be a pleasant experience. </p><figure class="kg-card kg-image-card"><img src="https://jochen.kirstaetter.name/content/images/2023/12/PXL_20231110_155924925.jpg" class="kg-image" alt="DevFest Dar es Salaam 2023" srcset="https://jochen.kirstaetter.name/content/images/size/w600/2023/12/PXL_20231110_155924925.jpg 600w, https://jochen.kirstaetter.name/content/images/size/w1000/2023/12/PXL_20231110_155924925.jpg 1000w, https://jochen.kirstaetter.name/content/images/2023/12/PXL_20231110_155924925.jpg 1280w" sizes="(min-width: 720px) 720px"></figure><p>Plus, Mary Jane already told me since a while that she would love to go there to check out tanzanite gemstones for a piece of jewelry she'd like to create.</p><h3 id="getting-around-in-dar">Getting around in Dar</h3><p>Planning to go to a new location, whether it's a new city, a new country, or both, involves checking out the options to get around. First problem to solve, how to get from the airport to the guesthouse and back, then how to go to and from the DevFest venue, and lastly how to explore other sights of importance while being there.</p><p>Organising a ride from the airport to the guesthouse was the easiest. Thanks to the wonderful assistance of Naamini I had nothing to do. She arranged everything by asking her trusted driver to come to the airport to fetch us, and then drop us off at the guesthouse. She literally needed my flight details and destination only. Massive help and easy-peasy.</p><p>During conversations at the reception desk it became pretty clear that either Uber or Bolt might be the best option to book rides. The recommendation was to use Bolt as it seems to be less expensive and more flexible than Uber. So we gave it a try the next day in order to get from the guesthouse to the venue of DevFest. BTW, we booked a car rather than a tuk-tuk (auto rickshaw).</p><figure class="kg-card kg-gallery-card kg-width-wide kg-card-hascaption"><div class="kg-gallery-container"><div class="kg-gallery-row"><div class="kg-gallery-image"><img src="https://jochen.kirstaetter.name/content/images/2023/12/PXL_20231110_074410383.jpg" width="1280" height="1707" alt="DevFest Dar es Salaam 2023" srcset="https://jochen.kirstaetter.name/content/images/size/w600/2023/12/PXL_20231110_074410383.jpg 600w, https://jochen.kirstaetter.name/content/images/size/w1000/2023/12/PXL_20231110_074410383.jpg 1000w, https://jochen.kirstaetter.name/content/images/2023/12/PXL_20231110_074410383.jpg 1280w" sizes="(min-width: 720px) 720px"></div><div class="kg-gallery-image"><img src="https://jochen.kirstaetter.name/content/images/2023/12/PXL_20231111_134456800.jpg" width="1280" height="790" alt="DevFest Dar es Salaam 2023" srcset="https://jochen.kirstaetter.name/content/images/size/w600/2023/12/PXL_20231111_134456800.jpg 600w, https://jochen.kirstaetter.name/content/images/size/w1000/2023/12/PXL_20231111_134456800.jpg 1000w, https://jochen.kirstaetter.name/content/images/2023/12/PXL_20231111_134456800.jpg 1280w" sizes="(min-width: 720px) 720px"></div><div class="kg-gallery-image"><img src="https://jochen.kirstaetter.name/content/images/2023/12/PXL_20231112_042140044.MP.jpg" width="1280" height="1707" alt="DevFest Dar es Salaam 2023" srcset="https://jochen.kirstaetter.name/content/images/size/w600/2023/12/PXL_20231112_042140044.MP.jpg 600w, https://jochen.kirstaetter.name/content/images/size/w1000/2023/12/PXL_20231112_042140044.MP.jpg 1000w, https://jochen.kirstaetter.name/content/images/2023/12/PXL_20231112_042140044.MP.jpg 1280w" sizes="(min-width: 720px) 720px"></div></div><div class="kg-gallery-row"><div class="kg-gallery-image"><img src="https://jochen.kirstaetter.name/content/images/2023/12/PXL_20231110_072917244.jpg" width="1116" height="639" alt="DevFest Dar es Salaam 2023" srcset="https://jochen.kirstaetter.name/content/images/size/w600/2023/12/PXL_20231110_072917244.jpg 600w, https://jochen.kirstaetter.name/content/images/size/w1000/2023/12/PXL_20231110_072917244.jpg 1000w, https://jochen.kirstaetter.name/content/images/2023/12/PXL_20231110_072917244.jpg 1116w" sizes="(min-width: 720px) 720px"></div><div class="kg-gallery-image"><img src="https://jochen.kirstaetter.name/content/images/2023/12/PXL_20231110_072446723.jpg" width="1280" height="960" alt="DevFest Dar es Salaam 2023" srcset="https://jochen.kirstaetter.name/content/images/size/w600/2023/12/PXL_20231110_072446723.jpg 600w, https://jochen.kirstaetter.name/content/images/size/w1000/2023/12/PXL_20231110_072446723.jpg 1000w, https://jochen.kirstaetter.name/content/images/2023/12/PXL_20231110_072446723.jpg 1280w" sizes="(min-width: 720px) 720px"></div></div></div><figcaption>Adventures on the roads of Dar es Salaam, Tanzania</figcaption></figure><p>Later on, we felt more comfortable and went all in, either using Bolt rides or bargaining with the tuk-tuk drivers at their stand to agree on a fair. It was really good fun to discover places like this.</p><h3 id="maasai-warriors">Maasai Warriors</h3><p>Already back at the guesthouse where we stayed but also throughout other places we noticed that there were Maasai warriors around. Some were there to do hotel services like bell boy, some did gardening, and others seemed to be security for single, female travellers. Maybe a reader from Tanzania could help me out here.</p><p>I found it really impressive!<br>Stupidly, I forgot to ask to take a picture with at least one of them. Oh well, probably next time then. However I got myself a Maasai Shuka. Only need to learn and practice how to wear it though.</p><h2 id="the-venue-">The Venue: 孔子学院</h2><p>Yup, that's the right place. Yes, I'm sure.</p><p>Honestly, I had no idea of what to expect when I saw the DevFest location first time. But hey,why not? It kind of makes sense that there is a Confucius Institute in Dar es Salaam, Tanzania. Given the importance of the port and international trade with China I seems quite helpful for students to have easy access to courses on Chinese language and culture. And while writing this blog I discovered there is a 孔子学院 in Mauritius, too. Who'd have known?</p><figure class="kg-card kg-gallery-card kg-width-wide"><div class="kg-gallery-container"><div class="kg-gallery-row"><div class="kg-gallery-image"><img src="https://jochen.kirstaetter.name/content/images/2023/12/PXL_20231111_100221345-1.jpg" width="1280" height="898" alt="DevFest Dar es Salaam 2023" srcset="https://jochen.kirstaetter.name/content/images/size/w600/2023/12/PXL_20231111_100221345-1.jpg 600w, https://jochen.kirstaetter.name/content/images/size/w1000/2023/12/PXL_20231111_100221345-1.jpg 1000w, https://jochen.kirstaetter.name/content/images/2023/12/PXL_20231111_100221345-1.jpg 1280w" sizes="(min-width: 720px) 720px"></div><div class="kg-gallery-image"><img src="https://jochen.kirstaetter.name/content/images/2023/12/PXL_20231111_062246046.jpg" width="1280" height="960" alt="DevFest Dar es Salaam 2023" srcset="https://jochen.kirstaetter.name/content/images/size/w600/2023/12/PXL_20231111_062246046.jpg 600w, https://jochen.kirstaetter.name/content/images/size/w1000/2023/12/PXL_20231111_062246046.jpg 1000w, https://jochen.kirstaetter.name/content/images/2023/12/PXL_20231111_062246046.jpg 1280w" sizes="(min-width: 720px) 720px"></div></div><div class="kg-gallery-row"><div class="kg-gallery-image"><img src="https://jochen.kirstaetter.name/content/images/2023/12/PXL_20231111_072621996.jpg" width="1280" height="765" alt="DevFest Dar es Salaam 2023" srcset="https://jochen.kirstaetter.name/content/images/size/w600/2023/12/PXL_20231111_072621996.jpg 600w, https://jochen.kirstaetter.name/content/images/size/w1000/2023/12/PXL_20231111_072621996.jpg 1000w, https://jochen.kirstaetter.name/content/images/2023/12/PXL_20231111_072621996.jpg 1280w" sizes="(min-width: 720px) 720px"></div><div class="kg-gallery-image"><img src="https://jochen.kirstaetter.name/content/images/2023/12/PXL_20231111_102536664.jpg" width="1280" height="712" alt="DevFest Dar es Salaam 2023" srcset="https://jochen.kirstaetter.name/content/images/size/w600/2023/12/PXL_20231111_102536664.jpg 600w, https://jochen.kirstaetter.name/content/images/size/w1000/2023/12/PXL_20231111_102536664.jpg 1000w, https://jochen.kirstaetter.name/content/images/2023/12/PXL_20231111_102536664.jpg 1280w" sizes="(min-width: 720px) 720px"></div></div></div></figure><h2 id="what-s-on-the-agenda-of-devfest">What's on the agenda of DevFest?</h2><p>Lots of amazing topics and sessions have been assembled by the GDG chapter in Dar es Salaam. Check out the <a href="https://sessionize.com/view/254byy8x/GridSmart?format=Embed_Styled_Html&amp;isDark=False&amp;title=DevFest%20Dar%20Es%20Salaam%202023">full agenda</a> on Sessionize to get an overview. Also, there had been multiple tracks in parallel allowing more speakers to present and give attendees a choice following their interest.</p><h3 id="networking-everywhere">Networking everywhere</h3><p>We managed to arrive a bit earlier than the times suggested on the agenda. This gave us time to get to know the team of GDG Dar a little bit, and to mingle with other attendees to get to know a bit more about their passions and activities. BTW, in one the rooms was even breakfast served. How cool is that?</p><figure class="kg-card kg-gallery-card kg-width-wide kg-card-hascaption"><div class="kg-gallery-container"><div class="kg-gallery-row"><div class="kg-gallery-image"><img src="https://jochen.kirstaetter.name/content/images/2023/12/DX4A8782.jpg" width="1280" height="853" alt="DevFest Dar es Salaam 2023" srcset="https://jochen.kirstaetter.name/content/images/size/w600/2023/12/DX4A8782.jpg 600w, https://jochen.kirstaetter.name/content/images/size/w1000/2023/12/DX4A8782.jpg 1000w, https://jochen.kirstaetter.name/content/images/2023/12/DX4A8782.jpg 1280w" sizes="(min-width: 720px) 720px"></div><div class="kg-gallery-image"><img src="https://jochen.kirstaetter.name/content/images/2023/12/DX4A9017.jpg" width="1280" height="853" alt="DevFest Dar es Salaam 2023" srcset="https://jochen.kirstaetter.name/content/images/size/w600/2023/12/DX4A9017.jpg 600w, https://jochen.kirstaetter.name/content/images/size/w1000/2023/12/DX4A9017.jpg 1000w, https://jochen.kirstaetter.name/content/images/2023/12/DX4A9017.jpg 1280w" sizes="(min-width: 720px) 720px"></div><div class="kg-gallery-image"><img src="https://jochen.kirstaetter.name/content/images/2023/12/DX4A8904.jpg" width="1280" height="853" alt="DevFest Dar es Salaam 2023" srcset="https://jochen.kirstaetter.name/content/images/size/w600/2023/12/DX4A8904.jpg 600w, https://jochen.kirstaetter.name/content/images/size/w1000/2023/12/DX4A8904.jpg 1000w, https://jochen.kirstaetter.name/content/images/2023/12/DX4A8904.jpg 1280w" sizes="(min-width: 720px) 720px"></div></div><div class="kg-gallery-row"><div class="kg-gallery-image"><img src="https://jochen.kirstaetter.name/content/images/2023/12/DX4A8819.jpg" width="1280" height="853" alt="DevFest Dar es Salaam 2023" srcset="https://jochen.kirstaetter.name/content/images/size/w600/2023/12/DX4A8819.jpg 600w, https://jochen.kirstaetter.name/content/images/size/w1000/2023/12/DX4A8819.jpg 1000w, https://jochen.kirstaetter.name/content/images/2023/12/DX4A8819.jpg 1280w" sizes="(min-width: 720px) 720px"></div><div class="kg-gallery-image"><img src="https://jochen.kirstaetter.name/content/images/2023/12/DX4A8846.jpg" width="1280" height="853" alt="DevFest Dar es Salaam 2023" srcset="https://jochen.kirstaetter.name/content/images/size/w600/2023/12/DX4A8846.jpg 600w, https://jochen.kirstaetter.name/content/images/size/w1000/2023/12/DX4A8846.jpg 1000w, https://jochen.kirstaetter.name/content/images/2023/12/DX4A8846.jpg 1280w" sizes="(min-width: 720px) 720px"></div><div class="kg-gallery-image"><img src="https://jochen.kirstaetter.name/content/images/2023/12/DX4A8477.jpg" width="1280" height="853" alt="DevFest Dar es Salaam 2023" srcset="https://jochen.kirstaetter.name/content/images/size/w600/2023/12/DX4A8477.jpg 600w, https://jochen.kirstaetter.name/content/images/size/w1000/2023/12/DX4A8477.jpg 1000w, https://jochen.kirstaetter.name/content/images/2023/12/DX4A8477.jpg 1280w" sizes="(min-width: 720px) 720px"></div></div><div class="kg-gallery-row"><div class="kg-gallery-image"><img src="https://jochen.kirstaetter.name/content/images/2023/12/DX4A8691.jpg" width="1280" height="853" alt="DevFest Dar es Salaam 2023" srcset="https://jochen.kirstaetter.name/content/images/size/w600/2023/12/DX4A8691.jpg 600w, https://jochen.kirstaetter.name/content/images/size/w1000/2023/12/DX4A8691.jpg 1000w, https://jochen.kirstaetter.name/content/images/2023/12/DX4A8691.jpg 1280w" sizes="(min-width: 720px) 720px"></div><div class="kg-gallery-image"><img src="https://jochen.kirstaetter.name/content/images/2023/12/DX4A8637.jpg" width="1280" height="853" alt="DevFest Dar es Salaam 2023" srcset="https://jochen.kirstaetter.name/content/images/size/w600/2023/12/DX4A8637.jpg 600w, https://jochen.kirstaetter.name/content/images/size/w1000/2023/12/DX4A8637.jpg 1000w, https://jochen.kirstaetter.name/content/images/2023/12/DX4A8637.jpg 1280w" sizes="(min-width: 720px) 720px"></div><div class="kg-gallery-image"><img src="https://jochen.kirstaetter.name/content/images/2023/12/DX4A8521.jpg" width="1280" height="853" alt="DevFest Dar es Salaam 2023" srcset="https://jochen.kirstaetter.name/content/images/size/w600/2023/12/DX4A8521.jpg 600w, https://jochen.kirstaetter.name/content/images/size/w1000/2023/12/DX4A8521.jpg 1000w, https://jochen.kirstaetter.name/content/images/2023/12/DX4A8521.jpg 1280w" sizes="(min-width: 720px) 720px"></div></div></div><figcaption>Some impressions and memories of DevFest Dar Es Salaam 2023</figcaption></figure><h3 id="gdes-and-a-googler">GDEs and a Googler</h3><p>Oh yes, you read this right. GDG Dar es Salaam managed to invite <a href="https://www.linkedin.com/in/khadija-%F0%9F%87%B0%F0%9F%87%AA-abdul-juma-26720143/">Khadija Juma</a> from Google. As she is based in Mombasa, Kenya it seemed an obvious opportunity and I was really happy to introduce Mary Jane to her.</p><p>As for GDEs, let me quickly list them in no particular order.</p><ul><li><a href="https://www.linkedin.com/in/ezekias-bokove/">Ezekias Bokove</a>, GDE for Google Cloud</li><li><a href="https://www.linkedin.com/in/mayeedwin">Maye Edwin</a>, GDE for Web Technologies</li><li><a href="https://www.linkedin.com/in/jochenkirstaetter/">Jochen Kirstätter</a>, GDE for Google Cloud</li></ul><p>The highlights of DevFest Dar were the ice-breaker game that was done at the beginning as well as the group photo outdoors. </p><figure class="kg-card kg-gallery-card kg-width-wide kg-card-hascaption"><div class="kg-gallery-container"><div class="kg-gallery-row"><div class="kg-gallery-image"><img src="https://jochen.kirstaetter.name/content/images/2023/12/PXL_20231111_072819899.jpg" width="1280" height="1030" alt="DevFest Dar es Salaam 2023" srcset="https://jochen.kirstaetter.name/content/images/size/w600/2023/12/PXL_20231111_072819899.jpg 600w, https://jochen.kirstaetter.name/content/images/size/w1000/2023/12/PXL_20231111_072819899.jpg 1000w, https://jochen.kirstaetter.name/content/images/2023/12/PXL_20231111_072819899.jpg 1280w" sizes="(min-width: 720px) 720px"></div><div class="kg-gallery-image"><img src="https://jochen.kirstaetter.name/content/images/2023/12/PXL_20231111_094908013.MP.jpg" width="1280" height="962" alt="DevFest Dar es Salaam 2023" srcset="https://jochen.kirstaetter.name/content/images/size/w600/2023/12/PXL_20231111_094908013.MP.jpg 600w, https://jochen.kirstaetter.name/content/images/size/w1000/2023/12/PXL_20231111_094908013.MP.jpg 1000w, https://jochen.kirstaetter.name/content/images/2023/12/PXL_20231111_094908013.MP.jpg 1280w" sizes="(min-width: 720px) 720px"></div><div class="kg-gallery-image"><img src="https://jochen.kirstaetter.name/content/images/2023/12/PXL_20231111_064958383.jpg" width="1280" height="1527" alt="DevFest Dar es Salaam 2023" srcset="https://jochen.kirstaetter.name/content/images/size/w600/2023/12/PXL_20231111_064958383.jpg 600w, https://jochen.kirstaetter.name/content/images/size/w1000/2023/12/PXL_20231111_064958383.jpg 1000w, https://jochen.kirstaetter.name/content/images/2023/12/PXL_20231111_064958383.jpg 1280w" sizes="(min-width: 720px) 720px"></div></div><div class="kg-gallery-row"><div class="kg-gallery-image"><img src="https://jochen.kirstaetter.name/content/images/2023/12/PXL_20231111_062749999.MP.jpg" width="1082" height="903" alt="DevFest Dar es Salaam 2023" srcset="https://jochen.kirstaetter.name/content/images/size/w600/2023/12/PXL_20231111_062749999.MP.jpg 600w, https://jochen.kirstaetter.name/content/images/size/w1000/2023/12/PXL_20231111_062749999.MP.jpg 1000w, https://jochen.kirstaetter.name/content/images/2023/12/PXL_20231111_062749999.MP.jpg 1082w" sizes="(min-width: 720px) 720px"></div><div class="kg-gallery-image"><img src="https://jochen.kirstaetter.name/content/images/2023/12/PXL_20231111_093804323-1.jpg" width="1280" height="837" alt="DevFest Dar es Salaam 2023" srcset="https://jochen.kirstaetter.name/content/images/size/w600/2023/12/PXL_20231111_093804323-1.jpg 600w, https://jochen.kirstaetter.name/content/images/size/w1000/2023/12/PXL_20231111_093804323-1.jpg 1000w, https://jochen.kirstaetter.name/content/images/2023/12/PXL_20231111_093804323-1.jpg 1280w" sizes="(min-width: 720px) 720px"></div><div class="kg-gallery-image"><img src="https://jochen.kirstaetter.name/content/images/2023/12/PXL_20231111_062409468.jpg" width="1280" height="1707" alt="DevFest Dar es Salaam 2023" srcset="https://jochen.kirstaetter.name/content/images/size/w600/2023/12/PXL_20231111_062409468.jpg 600w, https://jochen.kirstaetter.name/content/images/size/w1000/2023/12/PXL_20231111_062409468.jpg 1000w, https://jochen.kirstaetter.name/content/images/2023/12/PXL_20231111_062409468.jpg 1280w" sizes="(min-width: 720px) 720px"></div></div></div><figcaption>More impressions from DevFest Dar es Salaam. We had a great time in Tanzania</figcaption></figure><p>The Confucius Institute is quite impressive and it was really good fun to spend the day with DevFest attendees.</p><h2 id="thanks-to-gdg-dar-es-salaam">Thanks to GDG Dar es Salaam</h2><p>My heart-felt thanks go out to <a href="https://twitter.com/naaminiyonazi">Naamini Yonazi</a>, <a href="https://twitter.com/georgearwechu">Georgia Rwechungura</a>, the crew at <a href="https://gdg.community.dev/gdg-dar-es-salaam/">GDG Dar es Salaam</a>, and all WTM ambassadors involved in the preparation and organisation of DevFest Dar es Salaam. You are the real reason we had a wonderful time in Tanzania. Your early assistance and guidance helped us to feel welcome and at ease in Dar es Salaam. </p><p><strong>Asante sana!</strong></p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://jochen.kirstaetter.name/content/images/2023/12/GDG-Photo-505.jpg" class="kg-image" alt="DevFest Dar es Salaam 2023" srcset="https://jochen.kirstaetter.name/content/images/size/w600/2023/12/GDG-Photo-505.jpg 600w, https://jochen.kirstaetter.name/content/images/size/w1000/2023/12/GDG-Photo-505.jpg 1000w, https://jochen.kirstaetter.name/content/images/2023/12/GDG-Photo-505.jpg 1280w" sizes="(min-width: 720px) 720px"><figcaption>Women power: Khadija, Janice, Naamini and Georgia (left to right)</figcaption></figure><p>PS: We, Mary Jane and I, kind of already decided to visit Zanzibar during 2024, and we'd love to combine it with a future engagement with GDG Dar es Salaam, and who knows, maybe GDG Pwani in Kenya...</p><p><em>Photo credits</em>: Shared album on Pixieset by Sam Gidori, <a href="https://gdg.community.dev/gdg-dar-es-salaam/">GDG Dar es Salaam</a>.</p>]]></content:encoded></item></channel></rss>