[{"content":" Life happens outside of your comfort zone - everything else is just repetition ⭐️\nFor a long time, I\u0026rsquo;ve been thinking about giving a talk at a public conference. While I\u0026rsquo;ve already held technical knowledge-sharing sessions internally for colleagues or clients, I\u0026rsquo;ve never stood on stage in public.\nBack on the 27th of May 2022, I could tick off this item from my bucket list as I gave my first talk: \u0026lsquo;How fixing a broken window cut down our build time by 50%\u0026rsquo; at the Spring I/O in Barcelona. The conference had 1200 attendees and around 60 speakers. In total, more than 150 attendees came to my talk.\nThis article describes my journey to giving my first talk, including the lessons learned and how I prepared for this event.\nDeciding to Give a Talk There was this one item on my yearly goal list that I kept moving to my next year\u0026rsquo;s goal list.\nI was procrastinating a lot on giving my first public talk and always wanted to find the right moment. While I submitted some talk ideas to three different conferences, back in 2019, none of them got accepted.\nSomehow, though, by none of these submissions was I feeling that I really wanted to give this talk. It was a more self-obligated duty just to submit something so that I could tell myself I tried it.\nWhen the whole work-from-home period started, I first thought a remote conference might be an easy way to get started. However, I wanted to experience standing in front of a real audience and not staring into a screen.\nActually, I have seen many speakers complain that online conferences are sometimes even harder because you have no immediate feedback from the audience. Even worse, if every participant turns off their camera, you can\u0026rsquo;t see how the talk is going.\nThat\u0026rsquo;s why I decided to pause this goal and wait until in-person conferences were happening again.\nThen, somewhere around the beginning of 2022, I saw on Twitter that the CFP (call for papers) for the Spring I/O 2022 started. The Spring I/O is a community organized (mainly by Sergi Almar) conference in Barcelona, Spain. Its focus is on the Spring framework, the de facto standard framework (next to Jakarta EE and Quarkus) for developing Java applications.\nThe Spring I/O conference is a community organized conference and has no (direct) affiliation with VMWare. It was the 9th iteration of this conference and in the past, more than 1000 people participated.\nDuring the pandemic, they switched to a remote conference, and the conference in 2022 would be the first in-person conference after this break.\nI somehow felt that this was the right conference for me as it fits 100% to my blogging niche, and I knew various previous speakers that I could ask for help and insights.\nFor a long time, I\u0026rsquo;ve always had a talk idea in my head. It was regarding a project experience with a great learning analogy and background information. It was both full of actionable takeaways, lessons learned, and practical advice based on a real project on software development.\nAfter spending 30 minutes finalizing the talk title, elevator pitch, and description, I submitted the talk.\nI didn\u0026rsquo;t think this was too big of an audience for an unknown speaker with zero experience on a public stage. I thought, \u0026ldquo;Let\u0026rsquo;s submit the talk and see what happens\u0026rdquo;.\nGetting Accepted for the Conference On the 17h of March 2022, I got a positive COVID test result after feeling sick for almost two days 😣\nTo recover and relax, I enjoyed the entire day on my couch, surfing the web and watching YouTube videos.\nSomewhere around 3 pm that day, I checked my emails and found an email from the Spring I/O conference organizer \u0026hellip;\nI GOT ACCEPTED 🥳!\nAs there is some gap time between the deadline for the call for papers (CFP) and the day the organizers announce the lucky speakers, I almost already forgot about the talk submission.\nWhat a feeling of joy at this point despite having COVID and being sick.\nThat day was an entire emotional roller coaster. In the morning, the COVID test really shaped my day in a negative sense and I thought the day was over\u0026hellip;\n\u0026hellip; and then in the afternoon, I received a confirmation email that I was going to be a speaker at the conference. I couldn\u0026rsquo;t be happier. The sickness became secondary.\nLooking back, it seems that I was quite lucky being selected while having just one talk submitted. While many conferences allow you to submit multiple talks, I went all-in with this one. The main reason was that only for this particular talk I was feeling confident enough to present this idea as my first talk at a public conference.\nWith the talk being accepted, the countdown started, and it was time to prepare and train for the conference day. I only had the title, elevator pitch, and a description.\nI didn\u0026rsquo;t have a single slide yet \u0026hellip;\nThe Talk Idea The talk was about a journey and our lessons learned from optimizing our integration test setup and reducing the overall build time by 50% from 26 to 12 minutes.\nThe common thread throughout my talk was about the Broken Windows Theory. While this theory comes from the criminological area, it can be applied to almost everything.\nIn short, this theory describes that in rural areas where there\u0026rsquo;s much litter on the ground, damaged cars, and rundown houses, the likelihood that similar crime happens is more likely than in a neighbourhood where everything is spotless.\nWe can transfer this analogy to software projects. As soon as a team member introduces a not-so-optimal workaround to our code base, the more likely it is that other developers will follow. This can drain our overall project health as the first broken window entails potentially more broken windows.\nBack in 2019, I was working on a project where we had a broken window inside our codebase. It resulted in ever-increasing build times, and the overall team motivation started to decline. After some initial hurdles, we could fix this broken window and bring our project health back to a clean state.\nPreparing the Talk The requirements for this talk were crystal clear: I got 50 minutes. This includes the presentation and time for a live Q\u0026amp;A. As the audience is from all around the world (mostly Europe), the language had to be English.\nAs a rough ballpark figure, I was expecting 150-250 attendees for my talk as the overall conference had 1200 attendees and four parallel tracks.\nWhile I had some basic bullet points and ideas for the talk in mind, I did not start with the actual preparation until 60 days before the conference.\nI didn\u0026rsquo;t want to prepare my slides all at once and instead invested one to two hours daily in preparing the talk. I already had the main topic for the talk in my head and just needed to put my outline on paper.\nMost of the time, I worked on the talk in the morning so I could tick off this important item on my daily task list quite early. This continuous talk creation helped me stay creative and not work under pressure one week before the talk.\nI frequently switched places for this kind of creative work and primarily prepared the talk in cozy cafés or co-working places in Berlin:\nWhile I hadn\u0026rsquo;t done any major presentations in recent years, I picked Google Slides as this was the presentation software I was most familiar with. I picked a slide theme and adjusted it to my brand colors:\nIt was clear to me that I didn\u0026rsquo;t want to perform any live coding on stage for my first talk. That\u0026rsquo;s why I included all code examples as screenshots.\nFor the slide design, I tried to balance text-only and graphical slides (including memes) to keep the talk exciting, as I already knew I\u0026rsquo;d be the second last speaker on the Friday.\nFor training purposes, I gave the talk a week before the conference to myself and recorded the screen and my camera. This acted both as a trial run as well as a backup plan. Given the unclear COVID situation, I might have received a positive test and not be able to hold the talk. I thought that if I prepared the talk, I could send it to the organizers, and they could at least play the video for the attendees. Fortunately, this backup was not needed at all.\nI made this trial run as close as possible to the conference day. I used my standing desk and the presenter to get, as we would say in software development, as close to production as possible. This first run went fantastic, and I was just under time.\nThe second and final trial was done two days before the conference in a WeWork conference room in Barcelona. As I\u0026rsquo;m a bit superstitious, I thought that the final talk run had to be my third attempt, aka: all good things are in threes.\nThe First Conference Day: Relaxed Networking As the conference was in Barcelona, I used this event for some pre- and post-vacation that fitted around the conference in Spain 🇪🇸. I spent four days in Valencia before the conference and then drove to Barcelona by bus.\nIn the evening before the first conference, we had an amazing speaker dinner. There was even a shuttle that brought us to the dinner place. This speaker dinner was a great opportunity to meet the other speakers and connect with people I already knew virtually from Twitter.\nWe even went for a post-dinner beer on the rooftop bar of our hotel but got to bed around 1 am as most of us had their talk on the first conference day.\nAs my talk was on the second day, I could enjoy the first day. I went to many great sessions and connected with other speakers and people in the Spring Boot community.\nIt was a crazy feeling getting to the conference as a speaker. I was only an attendee at all past conferences.\nI felt really grateful, even feeling a little like a star, especially when I saw myself during the keynote as part of the speaker lineup.\nThe first day ended with beer and networking at the conference venue.\nAround 9 pm, there was even a huge fountain animation (Barcelona Magic Fountain of Montjuïc) next to the conference hall:\nAfter this show, I even got the chance to have dinner with the organizers and other speakers.\nAs my talk was happening on the second day, I was hesitant to stay up late and went straight to bed after dinner. This was at around 11 pm as the people in Spain eat quite late compared to my usual German dining hours.\nThe Second Conference Day: Giving the Talk Getting up in the morning on the day of my talk was both joyful and scary. I knew that by the end of the day, I would have stepped out of my comfort zone and held my talk. However, I had to make it through an entire conference day as my talk was the second-last.\nWatching other talks this day felt almost like being in school when it was time to hold presentations, and you were the last. You were sitting in the classroom, getting more nervous while more and more of your friends finished their presentations, and yet yours was still to come.\nGiven this slight mental pressure, I could still enjoy the entire conference day and only got really nervous and tired about one hour before my talk was due to start.\nFortunately, there was a 30-minute coffee break before my talk. Hence, there was no rush between two talks, and I could prepare the setup and get used to the stage and atmosphere. I arrived 20 minutes before the talk started, set up my machine, and connected to the beamer.\nWhile there were already some attendees sitting in the audience, most of them were enjoying their coffee break.\nI used this gap time to check some slides on the big projector and made sure to close all applications on my Mac that could disturb the talk.\nTen minutes before the talk started, I got the mobile microphone from the sound team. By then, almost fifty people were in the audience, some of whom I met either during the speaker dinner or the conference.\nRight on time, at 5 pm, the organizers closed the doors, and I started my talk\u0026hellip;\nFirst, I greeted the audience and thanked them that they came to my talk on a Friday afternoon at 5 pm while the weather was perfect outside in Barcelona.\nAfter the first 4 to 5 sentences, the initial peak of excitement and nerves faded away, and I started to really enjoy talking on stage.\nFortunately, there were no major technical problems during the talk as I didn\u0026rsquo;t live code and had all code examples stripped down to their minimum and included them as screenshots.\nAfter 48 minutes, I finished my last \u0026lsquo;Conclusion \u0026amp; FAQ\u0026rsquo; slide, and the talk was over.\nWhat a feeling!\nUnfortunately, the 2 minutes left weren\u0026rsquo;t enough to answer questions as the next speaker was lining up to give his talk in just 12 minutes.\nNevertheless, more than ten attendees came to me right after the talk to ask their questions and to thank me for giving this talk. We went outside the room to avoid any disturbance for the next speaker and discussed their questions with no rush.\nI guess it\u0026rsquo;s a good sign if there\u0026rsquo;s interest after your talk, and the attendees even miss the first minutes of the final talks as they want to talk with you.\nAfterthoughts \u0026amp; Tips Overall, it was one of the best experiences I have had in my professional career so far. The feeling of joy that I had finally worked out of my comfort zone really motivated me to tackle similar milestones from now on.\nTiming-wise I could have done a bit better. While my session was planned for 50 minutes, I finished my talk within 48 minutes and hence had no time to answer questions directly from the audience. Nevertheless, I tried to help everyone that came to me after the talk, and we took a standing desk outside to discuss details or specific problems.\nAfter giving the talk, I was both super happy and relaxed. I immediately pondered what talks I could prepare next, particularly as I enjoyed the entire experience of being a speaker at a conference.\nIn summary, these are the tips and recommendations I can offer as a first timer:\nDo at least one trial run. If you\u0026rsquo;ve never presented in front of a bigger audience, use an internal event or a meetup to train your talk and presentation skills Get a mentor or buddy to help out with the slide deck and talk preparation (I didn\u0026rsquo;t have one but advise you to do so if you\u0026rsquo;ve not done so many other public speaking sessions. Record yourself during your trial run(s). I know that it\u0026rsquo;s super awkward if you\u0026rsquo;re doing it for the first time. Cut your best trial recording to have a plan B if everything goes south. Imagine a positive COVID test right before the conference. This way, you can at least send the recording to the organizers, and they can play it inside the room. Check the hardware on stage during a coffee break a few hours before your talk starts. Have fun. You\u0026rsquo;re there to talk about stuff that you care about. Don\u0026rsquo;t do live coding during your first talk. Have a fallback option for everything: Batteries for your presenter, maybe a second laptop, a USB with the final talk on it, mobile data if the conference WLAN is flaky, etc. Use big font sizes - the attendees in the last rows will thank you! Don\u0026rsquo;t overuse bullet points, as they can make your audience tired Freshen up things with graphics, images, and short summaries Upload your slide deck to Speaker Deck afterwards Don\u0026rsquo;t use dark themes when screenshotting your code examples (I use the distraction-free mode of IntelliJ IDEA for my screenshots) Bring some water and maybe some throat candy to the stage in case your voice starts cracking Wear clothes that you feel comfortable in The final slide deck is available on Speaker Deck.\nKudos belong to Sergi Almar and his entire team for the fantastic organization of this event!\n\u0026hellip; and finally, here\u0026rsquo;s the recording of the talk:\nLet me know how your first public talk experience was in the comments. Also, feel free to provide any valuable feedback on the talk performance 🤓\nTo many more talks 🚀\nHave a good one, Phil\n","permalink":"https://progmot.com/post/giving-my-first-talk-at-a-public-conference/","summary":"Journey \u0026amp; Lessons Learned - Stepping out of my comfort zone to give a technical talk at a public conference in front of more than 150 developers.","title":"Giving My First Talk at a Public Conference"},{"content":" Newsletter around topics like productivity, freelancing, mindset, selling digital products, digital nomading, and motivation, all from the lenses of a software developer.\nOver the past five years, I\u0026rsquo;ve read many books, tried many business ideas, failed at some startups, and now want to share my lessons learned and recommendations.\nThe plan is to send a new piece of content sporadically. These updates are about 300 words long and tackle one specific topic.\nHere\u0026rsquo;s an excerpt of my current backlog of topics I\u0026rsquo;ll write about:\nGetting Started with Selling Digital Products (ebooks \u0026amp; online courses) Why I Reduced My Working Hours As an Employee My Morning Routine (Established Three Years Ago) How I Structure My Day As a Freelancer How I Run My Main Site and Sell Digital Products etc. This will be an exclusive newsletter, meaning that I won\u0026rsquo;t publish these updates on my blog. You\u0026rsquo;ll only get them in your inbox.\nIf you\u0026rsquo;re interested, join the newsletter below 👇🏻\nthis project is paused\n","permalink":"https://progmot.com/newsletter/","summary":"Right-sized inspiration around productivity, freelancing, mindset, and motivation as a software developer. Delivered frequently to your inbox.","title":"Progmot Newsletter 📬"},{"content":"These are your next steps to not miss any newsletter update 👇🏻\nConfirm Your Subscription We\u0026rsquo;ve just sent you a confirmation email to your inbox. Make sure to confirm the subscription by clicking the button or following the link.\nMake sure to also check your Spam and Promotions folder.\n","permalink":"https://progmot.com/newsletter/thank-you/","summary":"These are your next steps to not miss any newsletter update 👇🏻\nConfirm Your Subscription We\u0026rsquo;ve just sent you a confirmation email to your inbox. Make sure to confirm the subscription by clicking the button or following the link.\nMake sure to also check your Spam and Promotions folder.","title":"Thank You"},{"content":"This article describes a one-year journey of writing Stratospheric - From Zero to Production with Spring Boot and AWS as a co-author with two other co-authors that I met on Twitter. We\u0026rsquo;ve never met in person before and managed to successfully write a 450+ pages in-depth guide on developing and deploying Java Spring Boot applications on AWS (Amazon Web Services).\nIn short, this article covers:\nHow we self-published this ebook while writing the manuscript in Markdown How we promoted and sold the ebook How we organized ourselves to write the ebook asynchronously while having an 8-hour time lag General tips, recommendations, and lessons learned for co-authoring a technical ebook The whole project was (and still is) a lot of fun. I learned a ton about AWS and got the chance to connect and work with knowledgeable and smart people.\nThe three co-authors are: Tom (🇩🇪 living in 🇦🇺), Björn (🇩🇪), Philip (🇩🇪 - that\u0026rsquo;s me).\nLet\u0026rsquo;s get started 🚀\nHow We Found Each Other 👥 Luck is what happens when preparation meets opportunity.\nWhile scrolling through my Twitter feed, I saw a fellow technical blogger reaching out to other bloggers to exchange knowledge and ideas:\nI recently met informally with a couple of other dev bloggers via Zoom and I learned a lot. I would like to make that more official by creating or joining a meetup or something. Anyone know of such a meetup? Anyone interested to join and help organize such a meetup?\n\u0026mdash; Tom Hombergs (@TomHombergs) July 2, 2020 I immediately wrote Tom a DM and said I was in.\nNext, we met as a group of six tech bloggers to share our experience and lessons learned. During the second or third meeting of this kind, Tom asked for fellow bloggers who\u0026rsquo;d interested in taking a closer look at AWS and Spring Boot and who may want to write about it.\nBjörn and I, participating in this meeting, raised our hands. We\u0026rsquo;ve never met each other before and only partially knew each other from reading each other\u0026rsquo;s blogs and Tweets.\nWe organized a separate meeting for this potential AWS project to discuss more details.\nOur Goals For This Project ⭐️ Before we started to work on this project, we met several times to get to know each other and align our goals and expectations. While all three of us were working full-time for clients/an employer, we set the common understanding that this would be a fun side-project.\nWe all have had some experience with AWS but wanted to learn more about this particular cloud provider in depth. When developing features for clients or customers, we usually never had the time to explore the variety of AWS services available.\nOne primary goal of this remote writing project was to get better at developing Java applications on AWS. As Spring Boot was our default technology stack back then, the choice came naturally to write about this niche.\nWhile there are many books on AWS in general, none talks about the full cycle of bringing a Java Spring Boot application to production on AWS.\nShowcasing shiny features and machine learning capabilities of AWS is great, but many teams still struggle to design an automated CI/CD pipeline to push their changes automatically to AWS.\nFurthermore, the development journey doesn\u0026rsquo;t stop when merging the code changes and moving a Jira ticket to the done column. Now, the fun part begins as our code runs in production.\nIf we are in the lucky position to maintain and operate our own services (DevOps done right), we will have to deal with the following questions, which will arise sooner or later:\nHow do I know my service is healthy and operating as expected? What\u0026rsquo;s the current average response time for my most important API endpoint? What happened with the application yesterday night? Our support team got a user complaint. Where can I find and filter the logs from last Sunday? etc. In short, this brought us to the following high-level goals for our readers that also influenced our manuscript:\nLearn about AWS and IaC (Infrastructure as Code) with the AWS CDK. Develop a Spring Boot application with meaningful features (e.g., email notifications or OAuth2 login) while integrating as many AWS services as possible. Becoming familiar with best practices for running Spring Boot applications in production on AWS: monitoring, alerting, observability, etc. Apart from these project goals, I had the following personal goals:\nLearn more about AWS. Improve writing skills and tick off \u0026lsquo;writing a book\u0026rsquo; from my bucket list. Create awareness of myself to attract potential clients as a freelancer. Packed with these ideas, we then got started with the project.\nHow We Got Started 🛫 We then started to meet constantly every two weeks via Zoom and created a Slack workspace for communication and coordination. We organized ourselves in a Scrum-like setup and planned our two-week sprints with a Trello board. These bi-weekly Zoom calls were a mix of a daily review and a planning session.\nThere wasn\u0026rsquo;t any story point or product owner, we were all intrinsically motivated to get stuff done and used positive peer pressure, as everyone was reporting what they achieved in the last two weeks.\nAs a first step, we wanted to develop a small proof of concept application to explore which areas we could write about. We wanted our readers to complete the journey from knowing only a bit about AWS to having an automated CI/CD pipeline that deploys their application to production.\nWe picked what we felt most comfortable with for the tech stack: Java and Spring Boot with Spring Cloud AWS.\nBesides exploring AWS services on the go, we all had stories and best practices for various AWS services to share that the other co-authors could learn from.\nOnce we had a working sample application running on AWS and we were confident that the topic we were about to write added value, we started writing the book. We first sketched out a table of contents and added bullet points to the different chapters in parallel.\nWe created a new AWS account for this project, and added three IAM users for us. Next, we created a GitHub organization that acted as an umbrella container for all related code repositories for this ebook project.\nWe more or less split this proof of concept time into two areas: automating the infrastructure setup with CloudFormation and developing a sample application. Back then, we started with .yaml CloudFormation templates but moved quickly to the promising AWS CDK project.\nAs soon as we had a container cluster (ECS) with an automated CI/CD pipeline and the sample application with some basic features ready, such as a login with AWS Cognito and storing data within RDS, we started to plan the next steps.\nThis pilot phase took about two to three months.\nNext, we had to decide how we would write this book. The main question we had to answer was: Should we talk to a publisher and pitch our idea or self-publish the whole thing?\nAs this project was a side-project for all three of us and not what we do full time, we all agreed that working with a formal publisher was not an option for us: Working towards given deadlines and having to deliver a final piece on a fixed date was something we clearly wanted to avoid.\nFurthermore, Tom already self-published his first book and then got a technical publisher on board to offer a print version and more distribution channels. Based on his experience and our common understanding, that this project may also fail, we went for the self-publishing route.\nFor self-publishing books in the tech space, Leanpub seemed to be the de-facto default choice. Leanpub is highly appealing to self-publishing tech authors as they offer the following:\nWriting the manuscript in Markdown or bringing your own PDF Automatic formatting/layout for Markdown manuscripts Integration with GitHub/Dropbox for the manuscript Fair pricing with 80% royalties for the authors Automatic file generation for other ebook formats like Mobi and ePub Payout via PayPal and support for multiple authors No payment/tax implications for the authors: Leanpub acts as the merchant of record and takes ownership for the payment and tax handling (something I should have also favored for my first online course) Leanpub is also built around the \u0026ldquo;Publish Early, Publish Often\u0026rdquo; concept. They favor the approach of giving access to a book early while it\u0026rsquo;s still in development and continuously adding new chapters to it.\nEach Leanpub ebook has its own landing page with basic information about the book and information about its completeness:\nLeanpub even allows creating preview versions of the ebook, a feature we heavily used to see a rendered version of our recent changes. This helped us quite a lot when preparing a new ebook version.\nWe went for Leanpub because it\u0026rsquo;s tech-friendly, easy-to-setup and offers fair royalties that the platform can automatically split between co-authors.\nHaving signed up for Leanpub, it was now time to finalize the technical setup to then get our hands dirty and start writing.\nWorking daily with GitHub, we chose a private GitHub repository for backing our manuscript Markdown files. This allowed for a more seamless flow compared to uploading the files to a shared DropBox folder. We get versioning, automations with GitHub Actions, collaboration tools, and a great feedback mechanism via pull requests with GitHub.\nWe used the following branching strategy for the ebook:\nmain: generate ebook releases on Leanpub preview: generate previews on Leanpub personal-feature-branch: every co-author works in isolation on their next chapter Every co-author would work on their own branch and push their chapters to their dedicated branch. Once completed, we created a pull request to merge into the preview branch. This triggered our review process, where all other co-authors reviewed the new section one after the other.\nWhat\u0026rsquo;s great about this review process is that we could leverage the review features of GitHub. This allowed the reviewer to directly make suggestions like fixing a typo or structuring the sentence. These suggestions could be then added automatically by the review owner:\nThis way of working felt way more convenient than using a PDF reader, making comments and annotations to the file, and then sending it over to the owner of the changes.\nAfter the review had been completed by both co-authors (six-eyes principle), we integrated the change into the preview branch to collect multiple chapters for the next release. Once every two months or so, we created the next work-in-progress release by merging the changes to the main branch.\nAll that\u0026rsquo;s left to do then is to click the release button inside Leanpub to build a new digital version of our ebook. Theoretically, we could even automate this and publish a new release for the main branch on each commit.\nGetting the First Readers aka. Early Feedback 📖 Given the fact that we had figured out how to sell the ebook and how to write it, we now had to start, well, actually writing the ebook.\nWe found how to split the work and who would write what based on our own interests naturally. While Björn and I were more focused on implementing features for the sample application and connecting various AWS services, Tom was more into the CI/CD and infrastructure setup.\nWhile we had a rough idea and an early draft for our planned table of contents, we adjusted our plans along the way.\nWorking on a new chapter/feature usually involved some background fact-checking, consulting the AWS documentation and other blogs, developing the code changes, and then writing the chapter.\nFor some concrete examples, these are chapters we worked on:\nGetting Started with the AWS CDK OAuth2 Login with AWS Cognito Storing Entities to PostgreSQL using RDS Structured Logging with Amazon CloudWatch etc. While we had implemented similar features in the past, we still spent a reasonable amount of time reading the AWS documentation and related blog posts to ensure our previous assumptions were correct.\nWe also ensured every co-author worked independently on their own topic (like OAuth2 login or RDS setup) to avoid any misunderstandings or coordination overhead.\nEverybody was working on a dedicated chapter, so there wasn\u0026rsquo;t any conflict or idle time due to waiting on someone else\u0026rsquo;s input. Writing the new chapter consisted both of doing research, adjusting the sample application, and writing the manuscript.\nAs we were incrementally releasing a new version of the ebook, we tried to work on the modules and chapters in sequence. It should be more or less an append-only of chapters and no inline adding of chapters so that the readers who get a copy early on can continue reading the book where they left off once there\u0026rsquo;s a new version available.\nIn parallel to our first release preparation, we created a basic landing page and signed up for a mailing list provider (ConvertKit back then). To keep things simple, we bought an HTML Bootstrap theme and used GitHub pages to quickly launch this landing page and add the mailing list signup form to allow potential readers to get more information about our progress:\nAs there weren\u0026rsquo;t any earnings, we kept the costs low to only invest more $$$ once we saw adoption of our book.\nIn a true MVP fashion, the signup form on our landing page also acted as a preliminary litmus test. We could see how many developers are interested in bringing this book over the finish line.\nBefore releasing the first version, we had to finalize our ebook title and find a logo and a cover.\nAs the book is all about getting ready for the cloud and effectively deploying applications to production in the cloud, the icon of a launching rocket seemed suitable. We started with the placeholder project name aws101. However, as this was clearly violating the trademarks of AWS, we had to find another name.\nAfter some brainstorming for possible names, we ended up with Stratospheric. Much like the rocket icon, that term fits the cloud metaphor quite nicely.\nWe ordered two design examples for the logo on Fiverr and picked the best one:\nOn the 8th of November 2020, the time had finally come. We released the first manuscript with roughly 20% of the final content.\nWe started with a base price of $10, which we increased with each revision. Remember, that we get 80% royalties to be split equally among all authors.\nIterate For 6-7 Month ✍🏻 What followed were multiple months of meeting every two weeks, discussing the next steps, and writing the book. This step-by-step approach allowed us to react to early reader feedback and stay motivated as we could release something out to the world.\nI\u0026rsquo;ve used this same iterative approach with an early bird audience for my first online course.\nWhile you may have the best ebook or product, if your potential readers and customers are not getting in front of it, it may be a waste of time.\nAs all three of us run a blog anyway, have an audience on Twitter, and some of us a mailing list, we started off with an existing target audience.\nTo spread the news about our project, we tweeted about our current progress occasionally. To stay in touch with existing and potential readers, we tried to get as many of them on our landing page to sign up for our mailing list.\nWe used both our social media channels and the mailing list to provide teasers and give constant updates about our progress. We wrote a mailing list update and slightly increased the price whenever we released a new version. This created scarcity for the existing audience to get the copy early while the manuscript was still in development.\nFurthermore, we rotated among all co-authors to mix up the person in charge of writing the mailing list update.\nThose who got their ebook early got it for the lowest price, which is fair as they trusted our project from day 1.\nWhile we originally planned to use AWS CloudFormation templates for our infrastructure setup, we decided to rework the existing setup and use the AWS Cloud Development Kit (CDK). The AWS CDK was already getting more and more traction at the time, and this would also be a huge USP as not much of the available literature is already using the CDK.\nOn a high level, we ended up with these main modules for the ebook:\n1. Getting Started with AWS\nGetting used to AWS, its interfaces, its services, the management console, and how to automate the infrastructure deployment. This includes an introduction to the AWS CDK, our custom CDK constructs Java library, and some design decisions for building a CI/CD pipeline with GitHub Actions.\n2. Building the Sample Application\nNext, we dive into the actual application development. We showcase building must-have features while connecting to various AWS services:\nOAuth2 Login and user management with AWS Cognito Email delivery with SES Real-time browser notifications with WebSockets and Amazon MQ Asynchronous workload operations with AWS SQS Storing data in a relational database with RDS We showcase the integration with AWS and Spring Boot based on meaningful feature implementations and enrich our sample Todo application with every chapter.\n3. Operating and Monitoring and Applications in Production on AWS\nProduction is where the fun begins. We don\u0026rsquo;t stop after developing the last feature and also cover monitoring and operating our Spring Boot application in production. This includes topics like structured logging, Amazon CloudWatch alerts, emitting metrics, creating operational dashboards, etc.\nLooking back, these were the times we released a new work in progress ebook version:\nRevision 0.1 (20% complete): 2020-11-08 Revision 0.2 (35% complete): 2020-12-20 Revision 0.3 (50% complete: 2021-02-14 Revision 0.4 (80% complete): 2021-04-10 Revision 0.4 was our last pre-release, and we got our book to 80% at that time.\nWhile we almost constantly released a new version every two months, the remaining 20% was the hardest part and took the longest (as usual, Pareto principle applies) \u0026hellip;\nPublishing Version 1.0 🥳 The last release was the one that took the longest. As is well-known, not only in project management, the remaining 20% of a project is where the most time is spent\u0026hellip;\n\u0026hellip; this was also true for us.\nWe had some final content to write, but our most considerable effort went into final proofreading and alignment of the manuscript.\nWith three people on the team, everyone was doing their screenshots, custom diagrams, header structure, etc., slightly differently. However, we wanted to have a common, consistent style throughout the book.\nFurthermore, everyone had a different understanding on when to use a bold, italic statement, or when to use an info box, for example. This was something we wanted to unify across the book.\nNext, we also replaced some of our architecture and information diagrams with nice-looking Excalidraw diagrams:\nThese finalization parts took almost two months as we also read the ebook from start to finish several times. We took the task of proofreading ourselves and did not hire someone to do this.\nIn total, we ended up with 450+ pages of high-value content about Spring Boot and AWS.\nThe version 1.0 was to be both feature-complete as well as polished. We knew that our ebook journey didn\u0026rsquo;t stop there but wanted to move the completion needle on Leanpub to 100%.\nAs the finalization of the manuscript went closer, we thought about the best possible way to announce and release version 1.0.\nWe were invited to the German AWS Podcast by Dennis Traub (AWS Developer Advocate) and could talk about our own AWS cloud journey and advertise the ebook a bit.\nOn top of this podcast, we decided to organize an online release party and invited both the existing ebook readers from our audience and other interested people.\nWe prepared a one-hour agenda for this release party, where we talked about the book\u0026rsquo;s content, showcased the sample application, and the CI/CD workflow. We also had some time left for a Q\u0026amp;A session.\nFrom the ~50 accepted invitations, twenty people showed up on a Sunday afternoon (1st of August 2021) to celebrate the release with us.\nAfter fifty minutes into the call, we released the final version of Stratospheric together with the audience by hitting the \u0026ldquo;Publish Now\u0026rdquo; button in Leanpub together live during the video call.\nStratospheric 1.0 is released 🚀\nThanks to everyone that joined the release party on Zoom and hit the release button together with us (@bwilmsmann, @TomHombergs, and me) 🥳 We\u0026#39;ll upload the recording in the next few days ✔️https://t.co/I9yT9pwbuq pic.twitter.com/8H42ceKlDX\n\u0026mdash; Philip Riecks (@rieckpil) August 1, 2021 We recorded this release party for those that couldn\u0026rsquo;t make it to the live event on the 1st of August 2021 and uploaded the video on YouTube:\nWe were all super happy with the outcome of the release party and with our progress.\nAt that time, we already had 500 readers and got more and more attention.\nLife After the 1.0 Release 📈 A book is never finished; it\u0026rsquo;s abandoned. (Gene Fowler)\nWhile still being euphoric about releasing finish the first version of this book within one year, we knew that our journey wouldn\u0026rsquo;t stop here. Right after the release party, we all took some time off and focused more on spreading the news about the release rather than planning what was next.\nSince the release of version 1.0 in August 2021, we have seen tremendous adoption. The feedback from the readers is also excellent. We also created a Slack channel for Q\u0026amp;A and general communication for the ebook community.\nBoth Spring Boot and AWS are more or less mature, at least in the areas that we talk about: SQS, SES, RDS, web development, etc. Still, there\u0026rsquo;s much going on for the library that we\u0026rsquo;re using for integrating AWS services (Spring Cloud AWS). Furthermore, we also learn even better practices or different ways of doing things.\nThanks to the agile nature of Leanpub and given the fact that we didn\u0026rsquo;t have to ship a physical book to our readers, we are still able to update the ebook post-delivery. Leanpub has a feature to notify the readers about a new version that they can then download for free.\nWhile we had no strict roadmap in mind, we all agreed to keep this book up-to-date to avoid a stale book.\nWhenever there\u0026rsquo;s a new update for our ebook, we send out a small release information email to our newsletter to give a short overview of the changes:\nOn the financial side, we don\u0026rsquo;t get rich from selling this book. It\u0026rsquo;s some additional pocket money for us in the range of $150-300 for every author each month.\nTo increase the visibility of our ebook, we listed it on Amazon Kindle. While Amazon\u0026rsquo;s royalty rules are not that generous compared to Leanpub, we primarily publish on Amazon as well to get in front of more developers. Amazon is one of the most significant search interfaces after Google and YouTube.\nWe thought about a printed ebook version, but for now, we postponed this move as we believe our audience is more interested in reading technical books on their devices anyway. However, at least I\u0026rsquo;d like to have a physical copy of this book on my bookshelf sometime in the future.\nBased on the feedback received so far, we also decided to build an online course on top of the ebook to provide some more in-depth coverage of various areas. Given my existing experience with creating and launching technical online courses, this will be a great opportunity to apply my lessons learned from my first courses.\nGetting to the end of the book, some publishers started to reach out to us. They wanted to publish Stratospheric from their publishing house and bring it to various marketplaces. The additional outreach may be significant, but the royalties are fairly small compared to Leanpub, especially when split into three equal parts.\nTo stay independent, we opted against a publisher and published the ebook ourselves on Amazon to at least have the enormous search traffic coming from this major e-commerce platform. We know that Leanpub is a niche site, and not all developers are aware of this great source of technical books. However, given our existing audience from our blog, newsletter, Twitter, etc. we can easily make our potential readers aware via those channels.\nAt the time of writing this article, we have 800 readers, which is a great success 🥳\nRecommendations, Tips \u0026amp; Tricks, and Lessons Learned 🎩 What follows is an unordered list of hints and tips about this journey. If you plan to start a similar project, make sure to learn from our mistakes and recommendations.\nWrite Together, Not Alone Writing a book together has a lot of benefits. It motivates you to keep going when you would otherwise have quit when working on your own.\nWe committed to delivering something every two weeks and had some high-level ideas regarding when the next release would be published. This goal-based approach allowed us not to veer off, but work towards the next milestone.\nEspecially if you\u0026rsquo;re writing your first book, going it alone might feel like an insurmountable pile of work. Together, you get there step-by-step and can use the group\u0026rsquo;s momentum.\nFurthermore, when co-authoring a book, you\u0026rsquo;ll also improve your writing skills by getting constant feedback from other co-authors.\nWe all had some background in writing technical content, which helped us a lot. Starting such a project with three people who have never written any technical blog before might be burdensome.\nUse an Iterative Approach With an iterative approach, you don\u0026rsquo;t have to lock yourself for a year in a wooden cabin in Norway and come back with a finished book.\nStart small. Deliver small increments, do baby steps, and get feedback early.\nWe had a rough plan of what we wanted to cover but also adjusted a lot along the way.\nLeanpub is the perfect platform for this. Especially if you are a developer, you\u0026rsquo;ll really enjoy writing your manuscript in Markdown. No annoying formatting issues inside Word when trying to center images or tables.\nLeanpub does the layouting and file generation jobs for you. All you have to do is ship the manuscript.\nPick a publisher that supports early-access programs if you don\u0026rsquo;t want to go down the self-publishing route.\nYou might be super convinced about your idea and think it\u0026rsquo;s the most genius book ever. However, this doesn\u0026rsquo;t necessarily reflect reality. Get some early feedback mechanisms in place that help you quantify the interest. A mailing list or a dedicated Twitter account can be such a tool.\nUse Simple Tools Keep it simple. Use free plans and share the login with your co-authors if necessary.\nYou can scale the tools and costs with your ebook\u0026rsquo;s success.\nWe purchased a Bootstrap-based HTML theme for our landing page for some bucks and adjusted it to our needs. During the project\u0026rsquo;s inception phase, and while the ebook still wasn\u0026rsquo;t at 100% completion, we primarily used the landing page to attract potential readers. Our landing page had (and still has) a newsletter subscription form to keep potential readers around.\nWe started with the free plan of ConvertKit and recently migrated to MailerLite. The MailerLite pricing and plan structure was better for our needs.\nSome other tools/services that we used:\nGrammarly for fundamental proofreading and typos Writing the ebook in our editor of choice. I personally used IntelliJ IDEA most of the time. I tweaked the editor settings to wrap the lines so that I can write more naturally without having to scroll endlessly horizontally or buy a curved monitor. Fiverr for designing creatives, the logo, and the ebook cover GitHub for collaboration and review Google Sheet to keep track of our costs Slack for internal and external (with the community) communication Find a Schedule to Keep Momentum What helped us to keep the writing flow going was a fixed schedule. We met every two weeks for one hour and did a status update before planning the next steps.\nWhat worked for us was:\nA Trello board with four columns: backlog, in progress, to review, done Meetings via Zoom Document writing standards within the repository Use GitHub Actions for basic automations What personally worked for me was taking the first hour every morning to work on this project.\nAutomate What Can Be Automated As we all had a software developer background and mindset, we tried to automate everything that we could. We could even have automated the ebook publishing process using Leanpub\u0026rsquo;s API.\nGitHub Actions makes such automations almost effortless.\nAdding links for further resources is both a curse and a blessing. It allows the interested reader to dive deeper into a topic. However, the links disappear over time and may no longer be accessible as the content might have moved, or the site may have been shut down.\nWe automated the hyperlink verification with a small GitHub Action and an npm package that checks all links (also internal manuscript links) on each commit:\nname: Check for broken links on: [push, pull_request] jobs: broken-link-check: runs-on: ubuntu-latest name: Check for broken links in all Markdown files steps: - name: Check out source code uses: actions/checkout@v3 - name: Set up Node 16 uses: actions/setup-node@v3 with: node-version: 16 cache: \u0026#39;npm\u0026#39; - name: Install NPM packages run: npm install - name: Check for broken links run: npm run check-links Reach Out for Advertisement Start talking about your ebook on podcasts, conferences, and tweet about it as soon as possible.\nWe reached out to an AWS developer advocate (Ricardo Sueiras) during the inception phase to find possible ways of collaborating.\nAWS has sponsored us with some gift vouchers so that we could run the infrastructure (almost) for free. We even were able to contribute a two-part article on the AWS Open Source blog to gain some traction for our project:\nGetting started with Spring Boot on AWS: Part 1 Getting started with Spring Boot on AWS: Part 2 The German AWS Podcast by Dennis Traub (AWS Developer Advocate) was a fantastic way of spreading the word, too.\nAfter finishing the book, AWS even sponsored us for $2500 on GitHub.\nGet an Email Address for Every Author That\u0026rsquo;s an optional recommendation, but we had a good experience with having a dedicated email for each co-author and a basic catch-all email like info@yourbookname.com.\nWe\u0026rsquo;ve registered our domain within Amazon Route 53. We\u0026rsquo;ve built a simple self-made email forwarding with Amazon SES, S3, and AWS Lambda. If you\u0026rsquo;re curious about the implementation, check out the source code on GitHub.\nWork With Checklists Whenever there was something that we couldn\u0026rsquo;t or didn\u0026rsquo;t want to automate, we created a checklist for it.\nThis way, we didn\u0026rsquo;t forget a step for tasks we only performed occasionally.\nAs an example, this is our checklist for publishing a new ebook version:\nRotate the Responsibilities To avoid a single point of failure within the co-author team and mix things up, we rotated the various responsibilities.\nEveryone should release a new ebook version every now and then.\nWe also have an \u0026ldquo;author of the week\u0026rdquo; keeping an eye on our feedback channels. That person also is the first responder and coordinator for GitHub issues, Slack notifications, and emails.\nCentralize the Feedback Channels Right after the first readers got their copy, we started to get an increasing amount of messages via various channels:\nPrivate DMs on Twitter Emails to our ebook email address and/or private email address Slack messages Feedback via Leanpub GitHub issues etc. The various channels made it hard for us to keep track of all inquiries. Coordinating the response amongst the co-authors is difficult if someone gets a private Twitter DM.\nFurthermore, many of these feedback channels lack transparency. If we wrote an answer to a specific question via email, no other reader would benefit from the response as the conversation only happens within two inboxes.\nBack then, we decided to channel all feedback via public GitHub issues. Everyone can follow the status of the issue, can chime in, and see a list of already answered technical questions or feedback.\nTo streamline the feedback channel via GitHub issues and to ensure each issue contains some minimal required information (e.g., version of the ebook), we\u0026rsquo;ve created two GitHub issue templates: one for general feedback on the book and one for technical questions/issues with the sample application.\nThe GitHub issue template is backed by a YAML file and describes the required input fields:\nname: Feedback for the ebook description: \u0026#34;Everything related to the ebook: typos, layout issues, broken links, explanation gaps, inconsistencies, testimonials, etc.\u0026#34; labels: [ \u0026#34;ebook-feedback\u0026#34;, \u0026#34;triage\u0026#34; ] body: - type: markdown attributes: value: | Thanks for taking the time to provide feedback and improve the overall quality of Stratospheric! - type: textarea id: what-happened attributes: label: \u0026#34;What can we improve?\u0026#34; description: \u0026#34;Try to be as specific as possible - for example: On page 47, there\u0026#39;s a typo in the word \u0026#39;Strotospheric\u0026#39;.\u0026#34; validations: required: true - type: input id: version attributes: label: Version description: \u0026#34;Which ebook version are you referring to? You can find the version as part of the changelog (one of the last pages). Pick \u0026#39;latest\u0026#39; if you can\u0026#39;t find it.\u0026#34; validations: required: true - type: textarea id: suggested-change attributes: label: Suggested Changes description: What would you suggest to change or what do you expect as a reader? The rendered version of this template looks like the following:\nWhenever a reader now asks a question via any other channel, we redirect them to GitHub and ask them to submit their message there.\nDefine Rules for Typesetting and Structural Elements This would have helped us save some time for the final polishing and is one of our main lessons learned.\nThree different authors have three different opinions on when to use bold or italic script. Sometimes there are even four opinions if you forget which rules you applied yesterday.\nExamples of this include:\nWhen to use bold? When to use italics? When to use an info box? How to structure the headers? How to take a screenshot and which screenshot to take? What is an acceptable number of links on a book page? etc. We did not cover and align those rules in detail during our early manuscript reviews. During the final proofreading session, we encountered the issue of non-consistent sentence highlighting.\nAs a result, we now have some basic standards on when and how to highlight sections or single words.\nIf you\u0026rsquo;re starting from scratch, take some time with your co-authors to set clear definitions and create a one-pager for your typesetting rules.\nHave Fun That\u0026rsquo;s the most important takeaway. Find people you enjoy working with and from whom you can learn.\nIt\u0026rsquo;s a side-project, enjoy the experience, and learn as much as you can. It\u0026rsquo;s your spare time. If it feels like a job, don\u0026rsquo;t do it.\nDon\u0026rsquo;t expect to become rich by writing a book but instead, use this opportunity to establish a brand in your niche or use it as a way of establishing credibility and authority. I\u0026rsquo;m fairly certain co-authoring an ebook is more relevant than any basic certification for a specific topic.\nAbout the ebook Authors 🙋‍♂️ Tom Hombergs Tom is a seasoned software engineer with a passion for building systems in the simplest way possible. He is regularly blogging about Java, Spring, and AWS and is the author of Get Your Hands Dirty on Clean Architecture, giving hands-on advice on implementing a hexagonal architecture.\nFind out more about Tom on reflectoring.io and his Twitter profile.\nBjörn Wilmsmann Björn Wilmsmann is an independent IT consultant who helps companies transform their business into a digital business. He designs and develops business solutions and enterprise applications for his clients. Björn provides hands-on training in technologies such as Angular and Spring Boot.\nFind out more about Björn on bjoernkw.com and his Twitter profile.\nAdditional kudos belong to Björn, as he helped me finalize and proofread this article.\nPhilip Riecks (That\u0026rsquo;s Me) Under the slogan Testing Java Applications Made Simple Philip provides recipes and tips \u0026amp; tricks to accelerate your testing success and make testing joyful (or at least less painful). Apart from blogging, he\u0026rsquo;s a course instructor for various Java-related online courses and is active on YouTube.\nFind out more about Philip on rieckpil.de and his Twitter profile.\nQuick links:\nStratospheric ebook landing page Leanpub ebook landing page Source code for the sample application on GitHub If you have further questions or want some more details about a specific topic, let me know in the comments 👇🏻\nPS: You can get a copy of the Stratospheric ebook at a discount here.\nHave a good one, Phil\n","permalink":"https://progmot.com/post/self-publishing-a-book-with-almost-complete-strangers/","summary":"A two-year retrospect after co-authoring and self-publishing a technical ebook on Leanpub about Java, Spring Boot, and AWS with co-authors I met on Twitter.","title":"Self-Publishing a Book With (Almost) Complete Strangers"},{"content":"Excerpt of the projects I\u0026rsquo;m currently working on:\nStratospheric - From Zero to Production with Spring Boot and AWS (ebook \u0026amp; online course) Testing Spring Boot Applications Made Simple Blog (blog) Testing Spring Boot Applications Masterclass (online course) YouTube channel (hands-on videos) ","permalink":"https://progmot.com/projects/","summary":"Excerpt of the projects I\u0026rsquo;m currently working on:\nStratospheric - From Zero to Production with Spring Boot and AWS (ebook \u0026amp; online course) Testing Spring Boot Applications Made Simple Blog (blog) Testing Spring Boot Applications Masterclass (online course) YouTube channel (hands-on videos) ","title":"Projects"},{"content":"TL;DR: This 6500 word long article is a one-year retrospect after launching my first paid online course. Learn about my initial strategy, the actual journey, the mistakes I\u0026rsquo;ve made, and my recommendations.\nIt\u0026rsquo;s been a year since I launched my first paid online course: the Testing Spring Boot Applications Masterclass. There\u0026rsquo;s a lot of things I\u0026rsquo;ve learned along the way, and mistakes I\u0026rsquo;ve made.\nThis article gives you an inside view of this project. We\u0026rsquo;ll cover the technical setup, how I\u0026rsquo;ve planned and recorded the video lessons, and my sales and marketing efforts.\nA short note about my background: On my main blog, I create content about Java, Testing, Spring Boot, and AWS. In August 2020, I launched the Masterclass as my first paid online course. This online course is an in-depth resource on deploying Spring Boot applications with more confidence. The course showcases various recipes, tips \u0026amp; tricks, and best practices for testing real-world Spring Boot applications.\nDisclaimer: Figuring out which tools to use for such a project was quite an effort. Especially as I started from scratch. I spent various evenings screaming at my misbehaving checkout setup. I\u0026rsquo;ll reference the hardware, tools, and software I\u0026rsquo;m actively using at multiple places in this article. The marked links (*) are affiliate links. I paid the price (mostly time) to figure out this lightweight course selling setup - so you don\u0026rsquo;t have to.\nLet\u0026rsquo;s get started.\nThe Initial Strategy To better understand my journey, let\u0026rsquo;s take a brief look at my content creation history.\nBack in November 2017, I published my first blog article. While the first few articles were somewhat random (both in the topic and timing), I soon established the habit of writing about something consistently. Since then, I\u0026rsquo;ve been writing articles for various topics, mainly about Java and its ecosystem.\nMany of the blog posts result from my hands-on experience at work, or are tutorials I wish I had found on Google when I learned a new technology (especially Java EE).\nAt the end of 2019, I reached the milestone of 100 published articles on my site.\nAfter writing text/plain for three years, I thought the next natural step would be creating video content.\nI gave it a shot and uploaded my first video on YouTube in May 2019.\nThe audio quality was bad, and the video had black bars as I didn\u0026rsquo;t record 16:9. However, that didn\u0026rsquo;t matter, as I was happy to leave my comfort zone and have something uploaded. I was sure that the quality of every upcoming video would improve anyway.\nPerfection is the enemy of progress\nWith these two content platforms (blog \u0026amp; YouTube) in place, I continued creating content for various topics. There wasn\u0026rsquo;t a clear target audience I wanted to reach.\nWhenever a topic worth talking about popped up, I sat down and wrote about it. I usually switched frameworks between the articles and hence wasn\u0026rsquo;t targeting a specific set of Java developers.\nIn the last two years, I have naturally discovered my content niche. I started focusing more on one specific topic instead of serving all Java developers: Testing Java and specifically Spring Boot (a well-known framework) applications.\nThe benefit of this niche is that almost nobody talks about testing in their articles. They showcase shiny new features or tools, but nearly never tackle the testing part.\nThat\u0026rsquo;s quite frustrating if you want to apply their ideas to your project at work. You copy the relevant sections, make sure it compiles, and then hit a roadblock.\nYou know ahead that your colleagues will ask you as soon as you want to integrate your code changes: \u0026ldquo;Where are the (damn) tests?\u0026rdquo;.\nAfter creating some articles for this niche, I discovered that there was almost no online courses that comprehensively teach this topic, whilst using real-world examples.\nEveryone can test the add method of a MyCalculator class. But how do you write an end-to-end test for a modern application involving an OIDC login, database access, and fetching data from REST API in the background?\nMy plan was to develop a real-world course application, enhance it with an excellent test suite, and talk about it. And with real-world, I mean a sophisticated application that connects to various infrastructure components. This is where testing becomes tricky.\nI strongly believe that testing becomes joyful as soon as you know of the different testing tools \u0026amp; libraries, and recipes at hand.\nIt\u0026rsquo;s the HOW that\u0026rsquo;s important here.\nPacked with this mission, I was highly motivated to get this project going. As I have done nothing similar before, except some sporadic YouTube videos, recording everything up front would be a hell of work.\nThat\u0026rsquo;s why I decided to use an iterative approach and incrementally create this course while getting feedback early on. #agileDoneRight\nCreating the Course Content As a first step, I developed the real-world course application.\nThe course application is all about creating and managing book reviews.\nFor the application\u0026rsquo;s tech stack, I picked React with TypeScript and a Spring Boot Java backend. That should mirror most of today\u0026rsquo;s architectures (SPA connecting to a backend) out there.\nTo make the setup more advanced, I added Keycloak (an open source identity provider), PostgreSQL to store data, a remote REST API, and an AWS service for messaging to the mix:\nIn parallel, I sketched out the different course modules (module -\u0026gt; chapter -\u0026gt; lesson). Throughout the course, I wanted to tackle unit, integration, and end-to-end testing. This gave me the natural course structure of starting at the bottom of the testing pyramid with unit testing, and then working upwards until we finally write end-to-end tests in the last module.\nOnce the application was ready, I had a rough idea of what I wanted to showcase and talk about. I ensured there were enough non-trivial code parts to demonstrate various testing techniques: secured endpoints, message listeners, database access with native queries, plain business logic to verify, etc.\nWhile I could (and maybe should) have written the tests for the application alongside the development, I first wanted to have a working application to see the bigger picture.\nAs the goal of the online course was all about testing applications, I did not record the creation of the sample application. In various lessons, I explained the relevant code parts and gave an architectural overview at the beginning of the course. The overall application was sophisticated in the setup and yet simple enough to grasp within minutes.\nHere\u0026rsquo;s a short excerpt of the course application\u0026rsquo;s primary use case: Creating book reviews:\n(The GIF above is an automatically recorded outcome of an end-to-end test)\nWith my iterative course creation strategy in mind, I started with the first milestone and wanted to release the first two modules (roughly 15 course lessons). These two modules were all about getting used to the course application and an introduction to unit testing.\nThis initial goal got me started to outline the first lessons in greater detail. I noted down the best practices, tips, and pitfalls I wanted to show. I did not set hard boundaries for the lessons ahead and wanted to find a natural position to cut the recorded video afterward.\nNext, I opened my IDE and developed all the tests I wanted to write and talk about.\nOnce finished, I committed the changes to my private GitHub repository and removed the code I had just developed to a bare skeleton.\nThis \u0026ldquo;dry run\u0026rdquo; without recording helped me during the actual recording session. I was using two screens, and on one screen, I recorded my IDE and developed the tests step-by-step. On the second screen, I opened the target outcome by cloning the same project twice.\nI could frequently look at the second screen to not get lost while coding.\nThis initial batch of work (roughly 15 lessons, each 5-15 min long) kept me busy for three weeks. I usually used the morning hours to record 60 - 90 minutes of content. I brainstormed the following lessons in the afternoon and edited the videos once the entire batch was recorded.\nAfter finishing an iteration of usually 1 - 2 modules, I started with the next one. I followed this strategy until I had all eight course modules with 127 videos lessons recorded.\nThe Technical Recording Setup I\u0026rsquo;ve developed the course application and recorded everything on an Ubuntu 20.04 desktop PC and used the following tools:\nRecording \u0026amp; Editing:\nKazam for audio and screen recording Audacity for sound editing kdenlive for video editing and rendering Microphone: Auna Mic Application development:\na private repository on GitHub plain .md files inside the repository to structure the modules and lessons IntelliJ IDEA as the IDE: I used IntelliJ\u0026rsquo;s Presenter View to record the videos for a bigger font size and less clutter on the screen In addition, I used the Presentation Assistant plugin to automatically show the shortcuts I\u0026rsquo;m using (a lot of students will ask): As I was only recording my screen and audio, there was no need for a green screen, a high-resolution camera, or a lighting setup.\nHad I set up additional equipment for recording more than just my screen, this would have postponed the time I\u0026rsquo;d have a good enough recording setup.\nThe benefit of recording only audio and the screen is that you can focus on writing code. You don\u0026rsquo;t have to coordinate with the camera and can stare at your screen or microphone. If you misspelled a sentence, you can reiterate with ease.\nFor a first welcome video where you greet your new course participants, it might make sense to show your face to establish a stronger connection with the audience. For the rest of a technical course, IMHO, that\u0026rsquo;s optional.\nSometimes the face of the course instructor also blocks essential parts on the screen. As I\u0026rsquo;m only typing on my keyboard, there isn\u0026rsquo;t much gesture anyway.\nIt\u0026rsquo;s better to get started with a setup you feel comfortable with than procrastinating or getting pixel-perfect lessons that nobody will watch because the topic is not convincing.\nOnce I had the entire recordings for a batch ready, I started the editing process.\nAs a first step, I extracted the audio from the recording and opened it in Audacity. There I made some adjustments to the audio, like removing background noise. I replaced the original audio with the edited soundtrack from Audacity within kdenlive.\nNext, I started the actual video editing.\nI did not add any fancy animation or transition to the videos and only focused on removing the misspellings and separating videos. A 90-minute recording block usually resulted in 50 minutes of content split up into 4-5 separate video lessons.\nThe Technical Hosting Setup While I\u0026rsquo;ve worked through several courses on Udemy and similar platforms myself, I soon encountered that these platforms are not the best fit for me. While they do some marketing for your course and have a lot of search traffic, their payment structure is not what I was looking for.\nI wanted a lean technical setup that gives me full control over the course and audience.\nAs my blog is running on WordPress, and I\u0026rsquo;m heavily using the Thrive Suite* , I investigated their online course plugin: Thrive Apprentice.\nWith Thrive Apprentice, I could leverage the WordPress user management to have a login area and control access to my course. The visitors also stay on my side, and I have full control over the content.\nFor Thrive Apprentice* , you need both an eCommerce provider, and a video hosting solution.\nFor the eCommerce provider, I chose SendOwl, as their features and pricing (my current plan is $26/month) are reasonable.\nOnce I\u0026rsquo;d signed up for my SendOwl account, I connected my Stripe and PayPal accounts to have the most common payment options.\nThrive Apprentice supports various video hosting platforms. I went for Vimeo* and picked their paid plan for $6/month.\nCompared to YouTube, you can add more fine-grained security settings for your videos with Vimeo* . This makes unintended downloads and sharing more complicated. The integration with Thrive Apprentice works by simply copying the video link.\nUsing these tools, the final workflow to access the Masterclass is as follows:\nThe potential course participant visits the landing page Once they click on \u0026ldquo;Buy Now\u0026rdquo;, they\u0026rsquo;re redirected to a pre-checkout page (on my blog) and have to register a new course account They\u0026rsquo;re redirected to a SendOwl checkout page and enter their payment information SendOwl redirects the user to a \u0026ldquo;Thank You\u0026rdquo; page on my blog with further information on how to get started In the background (and if the user gave consent), they\u0026rsquo;re added to my mailing list ( Mailchimp* ), including order information Once the order is completed, SendOwl sends a webhook to my WordPress instance and Thrive Apprentice grants access to the purchased course The user can now work with the course and gets a \u0026ldquo;Welcome\u0026rdquo; email delivered to their inbox It took me some test purchases until I had the proper configuration for this setup, but since then, it\u0026rsquo;s working fine.\nSendOwl even offers a deep integration with Mailchimp* to recover abandoned carts.\nThe integration to my main mailing list also helps to segment my audience. I can see if a subscriber has enrolled for the course or got stuck in the checkout.\nThis helps to send marketing campaigns more efficiently to the right subscribers by using tags:\nSelling the Content Having the course idea and some early lessons uploaded to Vimeo* , now it\u0026rsquo;s time to sell the content, isn\u0026rsquo;t it?\nFrom a timeline perspective, I first created a minimal version of the landing page, including basic sales copy.\nThis helped me gather my thoughts and think about the benefits and the USP (unique selling proposition) of the course ahead. Figuring out a minimal sales pitch also gave clarity on what to focus on when I planned the course lessons.\nThe landing page at this time was the bare minimum (no checkout) and a static site on my blog advertising my current idea. I put a newsletter signup form on this early version of the landing page to capture potential customers.\nThis pre-landing page also acted as a basic market research opportunity. I used it to validate that the course idea arouses interest. Just because I thought the course topic was valuable, that didn\u0026rsquo;t imply that someone out there was willing to pay for it.\nFor the landing page I used Thrive Architect, a visual drag-and-drop page editor that is part of the Thrive Suite* . I picked one of their ready-to-use landing page templates to get started quickly.\nWhile I haven\u0026rsquo;t any screenshots of this early version anymore, here\u0026rsquo;s an overview of the final page:\nAs this was my first landing page for a paid product, I tried my best to write engaging sales copy. I added social proof via testimonials about myself from well-known content creators in the Java space as I didn\u0026rsquo;t have any course testimonials yet.\nAs soon as the first feedback from course participants came in, I asked for their permission and also placed them as testimonials on the page.\nMost developers don\u0026rsquo;t know you. You\u0026rsquo;re a stranger on the Internet. Why should anyone take your course?\nI shared the pre-landing page and my course idea on various channels (Twitter, LinkedIn, mailing list, etc.). After collecting potential leads for almost two weeks, I got 50 prospective leads.\nThis was enough evidence for me to get started.\nTo come up with a final price, I used other courses in my niche as an orientation and wanted to stand out with a premium course on this topic. Nothing in the Udemy price level. The first target price that came to my mind and seemed reasonable was $159 for the entire course.\nOnce the first video lessons were uploaded to Vimeo* , I modified the landing page and activated the checkout process.\nPaying the full price for the course up front while getting access to a subset of the lessons wasn\u0026rsquo;t a viable strategy. I came up with the idea of early-bird discounts similar to an early access program.\nWith every iteration of the course, I slightly increased the price. Those that joined early got access to the entire course for almost the price of an eBook. But they had to wait until all lessons were available.\nI added scarcity effects with a countdown that informs how long the current early-bird discount is available, to drive more sales.\nIn the end, I had nine of these early-bird batches:\n80% discount from 8th of August - 16th of August 70% discount until the 23rd of August 65% discount until the 30th of August 60% discount until the 13th of September 55% discount until the 20th of September 50% discount until the 27th of September 40% discount until the 4th of October 37.5% discount until the 11th of October 30% discount until the 25th of October At each stage, new course users could join for a reduced price and get all upcoming course lessons for free. This early-bird program also reduced the feedback cycle as I got important feedback early on and could improve the upcoming lessons.\nGoing Live With the First Lessons Selling something to an audience of zero people is hard.\nWhen I launched the first landing page, I already had an existing audience thanks to my mailing list, blog, Twitter account, and YouTube channel.\nThose people, however, all had different interests as my existing content was a diverse mix of topics. Not all of them were my perfect target audience: Java developers working with Spring Boot that want to improve their testing skills to deploy their application with more confidence.\nNevertheless, some early adopters were among my existing audience, which gave me an additional boost and confirmation that there\u0026rsquo;s demand for such a course.\nAfter the small market research phase, where I collected email addresses of potential leads on my pre-landing page, I started to advertise the course actively. As I was (and still am) highly convinced that my online course can improve the technical skills of many developers, I used all channels to raise attention about each early-bird phase.\nIn the beginning, my newsletter updates and Tweets might have seemed a little salesy as I was highly motivated to get the word out. I screwed some visitors and newsletter subscribers as they weren\u0026rsquo;t expecting this much advertisement.\nThat\u0026rsquo;s the price you pay for learning how to balance sales talk and content delivery.\nThe unsubscribe rate of my mailing list also started to increase. At first, it was hard to see subscribers leaving the mailing list whenever I wrote about the current progress or informed about the remaining days for the current early-bird batch.\nIn the end, as I can\u0026rsquo;t please everyone and wanted to shift my content niche, it was fine that some subscribers disappeared naturally.\nSince then, I started to focus on creating new content that is somehow related to my niche. This helped me get potential leads naturally as they subscribed with the intent to learn more about testing.\nOn the 8th of August 2020, the time had come to go live with the first video lessons and an 80% discount.\nI still remember the exact feeling when I hit the release button for this first early-bird batch. I was both nervous and super excited. While I tested the entire checkout process multiple times, I was still worried that something would go wrong.\nAs I didn\u0026rsquo;t want to nervously stare at my inbox for the first complaints or orders (who knows what will happen), I left my room and had dinner with my family to distract myself.\nI almost forgot about the launch and checked the Stripe (payment processor for credit cards) dashboard two hours later\u0026hellip;\nWTF?\nThere are already five sales - YEEEEEES!\nDamn, what a feeling.\nSomeone from somewhere around the globe just bought my course at this early stage. And they even paid for it!\nAt the end of the release day, there were nine paying customers:\nI never thought that many people would enroll in the course at this stage. I was expecting 20 customers in the first month.\nFrom release day onwards, I used almost every day to work on the remaining course lessons. It took me two and a half months to finish the course.\nA Note on Effort On the 25th of October 2020, when I uploaded the last lessons and closed the final early-bird batch, the course had 127 video lessons.\nI never had a target for the total course length in mind. I recorded as many videos as required to explain the various unit, integration, and end-to-end testing concepts.\nIn total, the course users will watch 10 hours of high-quality content on testing Spring Boot applications. Most of the video lessons are five to ten minutes long.\nIf I had started this project with the goal of 10 hours in mind, and wanted to record everything at once, that would have been almost impossible. I\u0026rsquo;d had to lock myself in my room for two months straight and then come out with a big bang release. The iterative approach helped me keep going.\nIt\u0026rsquo;s hard to tell how much effort went into this entire adventure as I didn\u0026rsquo;t stop and record the time.\nAs a ballpark figure, let\u0026rsquo;s say that for 30-minutes of video content, I\u0026rsquo;ve recorded 45 minutes. Editing the raw content took me another 45 minutes. This makes it approximately 90 minutes for a final content block of 30-minutes.\nHowever, this number does not include preparation work, coding efforts upfront, ideation, and marketing efforts afterward.\nIf I had to guess the total hours, it would be between 100 and 120 hours to create this course from scratch.\nThe additional time I had due to working remotely made this workload possible, next to a full-time job as a developer. I didn\u0026rsquo;t have to spend 2 hours every day for the commute and could focus on the course first thing in the morning. In addition, I spent some Saturdays and Sundays to make this course happen.\nNow it\u0026rsquo;s time to start with the one-year retrospect.\nOne-Year Retrospect - What Went Well Looking back at the first year of this adventure, let\u0026rsquo;s talk about what I would recommend and where I got lucky.\nReleasing Early and Often The iterative approach with small increments helped to experiment and keep being motivated.\nGetting the first version of your course out as soon as possible gives you confirmation and feedback early on.\nThis first version need not be perfect, but will let you test your setup end-to-end. This works way better than preparing a \u0026ldquo;big bang\u0026rdquo; release and then figuring out that something with the payment setup is not working at the last minute.\nWorking With a Good Enough Tech Setup You must be confident and have a simple and reproducible recording setup. You should be able to hit the record button in a matter of minutes with little preparation work.\nIf you have to set up an entire conference studio for your first online course, chances are high you\u0026rsquo;re procrastinating due to the effort.\nI can highly recommend getting some first touchpoints with video recording and editing on YouTube. YouTube is a great playground. There will be no refunds and (usually) only helpful comments to improve.\nThis applies to both the technical setup for recording and selling your course. There are many decisions to make, and I\u0026rsquo;d recommend that you start with the simplest solution that fits your current needs.\nYou can buy a green screen later.\nSingle Digit Refund Rates Money-back guarantees are a must-have for digital content. I\u0026rsquo;m offering a 30 days back no-questions-asked policy. I\u0026rsquo;ve had some bad experience with the refund policy of another content creator in the past and didn\u0026rsquo;t want to be alike.\nI still remember the first month after the launch of the first version, I was so nervous about the first 30-day period and thought many customers would ask for a refund.\nThis did not happen.\nAfter one year, I have a refund rate of 0.75%. Most of those refunds were due to different expectations.\nAffiliate Marketing is King There are tons of bloggers out there that might want some extra money each month to pay their hosting/tooling bills. I reached out soon to various other bloggers in the Java ecosystem and asked them to become an affiliate.\nIf the affiliate partner embeds their link into an article that talks about the topic you teach, the conversion rates can be excellent.\nThose affiliate links will also add social proof, and more developers will get to know you.\nSendOwl comes with an easy-to-use affiliate setup. One of my affiliate partners is making $200+ almost every month.\nAttracting New Leads With Compelling Free Content As soon as your existing audience knows about your product, you need to attract new leads.\nOne of the best ways to do this is by creating high-quality content around the course topic.\nOnce I found my niche, I doubled down on the testing topic and primarily created articles and videos for this domain.\nYour blog visitors will soon associate your blog with your niche. Even if they don\u0026rsquo;t convert on their first visit (which they rarely do), they know that they can come back to find a solution for problem X.\nAnd the next time they\u0026rsquo;re looking for deep dive content on your topic, they know where to look first for an online course.\nStarting With Market Research I got lucky that there was a demand for this course. It might have also flopped.\nThat\u0026rsquo;s fine, as long as you\u0026rsquo;re finding this out early in the process. Creating the landing page first can help to identify if there\u0026rsquo;s demand. You can also use a poll and send it to your existing audience.\nIf you don\u0026rsquo;t have an audience (yet), try to engage with your target audience on Twitter, Reddit, YouTube, etc.\nLiving Off the Earnings I guess most of you are eagerly waiting for the raw numbers \u0026#x1f4b0;\nI\u0026rsquo;ve made $35.369,44 in revenue after one year:\nThe margin is high as my only expenses are hosting fees, marketing costs, and affiliate commissions.\nIf I slightly reduced my monthly costs for living, I could live off that money.\nThat\u0026rsquo;s a huge relief!\nIn the first months, you might not get the traction as expected. Don\u0026rsquo;t compare the invested time with your hourly rate or salary.\nAn online course is an asset that\u0026rsquo;ll (hopefully) make money while you sleep.\nSteep Learning Curve There\u0026rsquo;s a lot to learn, not only about the topic you teach.\nI learned so much about marketing, writing sales copy, tracking, conversion rate optimization, A/B testing, checkout processes, online marketing, how to work on customer complaints etc.\nThis additional knowledge also helps me improve as a software developer, as I now see things from a different angle.\nI\u0026rsquo;m no longer just a techie and code monkey, I understand what it takes (at least the basics) to run an online business as I\u0026rsquo;m selling products on my own.\nStarting Small This steep learning curve is a double-edged sword.\nThere are so many topics to handle when selling digital products on the Internet:\nyour participants have a smooth and working checkout process the access to the course content is working your landing page has a reasonable page speed work on complaints create invoices do accounting work etc. You can easily get lost in various parts of creating, advertising, and selling your content.\nI usually stop when I have a good enough solution and come back later with a fresh mind and more hands-on experience.\nThere\u0026rsquo;s so much to do. Start small, and iterate.\nDon\u0026rsquo;t get frustrated if something\u0026rsquo;s not working immediately.\nCan\u0026rsquo;t find the root cause for your not-so-optimal page speed? Give your best and otherwise sleep a night over it.\nIt has to be joy, not work \u0026#x1f609;\nOne-Year Retrospect - What to Improve As the goal of every retrospective is to improve, let\u0026rsquo;s talk about my mistakes and the things I would do differently now.\nUse a Merchant of Record \u0026hellip; and thank me later.\nIf you\u0026rsquo;re selling to EU customers, pick a merchant of record to sell your digital products. Take a few minutes to read about VAT handling of digital goods (especially for EU customers), and you\u0026rsquo;ll thank me later. I didn\u0026rsquo;t read enough about this topic and started without such a middleman.\nI\u0026rsquo;m handling VAT for myself. The effort is manageable.\nWhen working with SendOwl, I can highly recommend Quaderno to stay tax compliant, create nice-looking invoices and exports for your tax advisor.\nIf I would start over again, I\u0026rsquo;d pick a provider that handles all tax implications. Possible providers are CopeCart or Digistore24.\nThat\u0026rsquo;s more time to focus on improving the course.\nAdjust Your Expectations for the Participation Rate I first thought my content was not good enough when I looked at the total views of the last module.\nI expected everyone to finish the course right after they purchased it, or at least in time (whatever this means). This is because this is what I usually do when I enrol on a new course.\nIt seems that this is not the case for everyone.\nThere are still course participants that did not even start with lesson one.\nThat\u0026rsquo;s okay - they might be busy and will start when they have time.\nUse IDEA Live Templates to Avoid Blockers While Recording During various recording sessions, I got lost.\nI sometimes forgot how to implement the test, what package to import or what I wanted to show.\nIntelliJ IDEA, the Java IDE I\u0026rsquo;m using, provides a feature to help: live templates.\nWith these templates, you prepare code skeletons and insert them with auto-completion.\nHowever, when using these templates, it\u0026rsquo;s important to find the right balance of magically inserting the code and typing everything from scratch.\nYou can\u0026rsquo;t just paste 15 lines of code and assume the course participant gets what you\u0026rsquo;re doing.\nSupport Purchase Power Parity from Day One We live in a world with different purchasing power and wages.\nThis $159 online course is affordable for someone working for working in silicon valley. That\u0026rsquo;s not the case for all other countries around the globe.\nA developer earning only a quarter of the US median wages thinks twice before enrolling in this course. For some developers, the course for its base price is not affordable at all.\nMany companies adjust the prices for their products and services to the purchasing power of each country. This way, the relative costs for a product (e.g., 5% of the median monthly salary) should be the same for everyone.\nIn the early days of the course, several potential customers asked for coupon codes because the price was too high for them. Back then, my main excuse for not integrating automatic price adjustments was that my eCommerce provider did not support something out-of-the-box.\nAfter some investigation, I came across a small library from Robin Wieruch that helped me integrate purchase power parity (PPP) with some additional coding effort on my end.\nAs I want to reach many people with the content I create, supporting PPP is a no-brainer for me in retrospect. Since the integration of PPP, the total orders have also increased.\nI\u0026rsquo;ve seen creators that are afraid that someone will abuse this mechanism.\nCreating a VPN tunnel to another country is a matter of seconds. Someone might trick this system and get the content for only a subset of the target price for their country. Nevertheless, I\u0026rsquo;m still able to see the origin of the payment and can identify frauds.\nThis has never happened so far, and even if it happens, I\u0026rsquo;m convinced that Karma will do its job.\nEmbed More Hands-On Exercises and Quizzes I\u0026rsquo;ve worked through several online courses and enjoy learning new techniques and tools this way. I generally prefer to code along with the course instructor and immediately try out things in my IDE.\nWhenever there were exercises or assignments at the end of each lesson, I usually ignored them as they were sometimes too simple or somehow already covered by me coding along.\nThis personal preference was the main reason not to include any specific coding task after each lesson. I thought that if customers are eager to learn this topic, they\u0026rsquo;ll try to apply the knowledge as soon as possible by default.\nOtherwise, it\u0026rsquo;s shallow learning, and if you\u0026rsquo;re not motivated, exercises might also not help that much.\nNot everyone shares this viewpoint, and some course participants have already asked for a more guided approach. Looking back, I would have thought more about exercises, quizzes, and assignments.\nFor learning new things, the best way to put it is in the words of Benjamin Franklin:\nTell me and I forget, teach me and I may remember, involve me and I learn - Benjamin Franklin\nAs I did not create a physical product that is already shipped to customers, I can still add these exercises afterward.\nStart Earlier I guess everybody has this learning curve after accomplishing something outside of their comfort zone.\nSeeing how easy it was in retrospect makes me wonder why I did not start earlier. Most of my fear when creating content on the Internet was what others think when they see it.\nWhen I created my blog and uploaded my first video on YouTube, I never actively showed anyone my project, and let them naturally find out. I don\u0026rsquo;t care at all what they think, except if it\u0026rsquo;s constructive feedback.\nAs long as I\u0026rsquo;m having fun doing it, and see the benefit for a greater audience, I\u0026rsquo;m happy.\nThere\u0026rsquo;s only one good time for creating your first article, YouTube video, or online course: right now.\nSpend Less on Display Ads or Spent It Better Seeing the sales coming in, I created ads on various platforms like Google Search, Twitter, Facebook, and LinkedIn.\nI thought that if I just had enough firepower (a.k.a. money) for ads, I\u0026rsquo;d create a money machine.\nLiving the dream where the CPA (cost per acquisition) is less than the generated revenue: a money perpetuum mobile.\nThat didn\u0026rsquo;t work - at least not for cold leads and a $150+ product.\nThe advertising domain was new, and the (sometimes complex) user interfaces to create new campaigns confused me. I had to burn some cash until I had the campaign setup right and targeted the right audience.\nMy first ads on Facebook, Twitter, and LinkedIn, were trying to create sales for the Masterclass. While these ads brought visitors to my site, nobody immediately converted. This is understandable for cold leads and a $150+ product.\nAfter spending over $2k+ for various platforms, I\u0026rsquo;m no longer advertising the Masterclass directly. This money might seem huge, but almost 50% was spent learning how display ads work.\nI\u0026rsquo;m still running display ads, but follow a different approach. I use the ads to make my target audience aware of my content and what my site is all about. If they like the content, they might sooner or later convert into a course participant for my Masterclass.\nWhile this is a slower sales process, it\u0026rsquo;s more sustainable, and right now, I generate leads for one of my free testing courses for about $0.50.\nFrom the Traffic Secrets book I learned that there are more or less four types of leads:\nThe potential course participant is not aware that they have a problem: a.k.a. - I don\u0026rsquo;t write tests The potential course participant is aware that they have a problem: a.k.a. - I try to write tests but fail to get the setup correct, and I\u0026rsquo;m constantly frustrated The potential course participant is aware of you as a content creator: a.k.a. - I know that Philip is creating some content about Java and Spring and have read one or two articles from him Being aware that you sell an online course that helps to fix this problem: a.k.a. - I know that Philip offers the Testing Spring Boot Applications Masterclass, which will help me write better tests -\u0026gt; Ka-Ching $$$ Connect With More Content Creators You don\u0026rsquo;t have to explore everything on your own. You don\u0026rsquo;t have to make all the mistakes on your own.\nMost of the stuff has already been solved by other content creators - ask them actively for advice and help. Ask them what they\u0026rsquo;d do differently if they\u0026rsquo;d start from scratch again. Ask them which tools they use and how their setup works.\nI\u0026rsquo;m sure most creators are happy to share insights and help you get started.\nRead retrospective articles like this and join communities like Blogging For Devs. Surround yourself with like-minded people for both support and motivation.\nDon\u0026rsquo;t Get Drained Into a Sales Dopamine Cycle Seeing passive money coming in almost daily, I soon started to check my mails after work eagerly (I never check my emails first thing in the morning). Subconsciously, I got drained into frequently checking my sales due to a small dopamine rush from each new order. It\u0026rsquo;s similar to the urge to check the Twitter feed, HackerNews, or Reddit.\nEach new customer gave me some gratification and relief until the point when there were no new customers for several days. I felt unhappy.\nInitially, I tried to run temporary discount campaigns to see at least some sales coming in. That wasn\u0026rsquo;t worth the effort as it screwed existing customers just for the purpose that I see this lousy sales graph go up.\nThat\u0026rsquo;s not worth it.\nIf your product is good and you have an established sales funnel, it\u0026rsquo;s only a matter of time until new course users join.\nThese sales ambitions might drain your creative resources, and you start focusing on the wrong ends: a.k.a. - getting more sales vs. making a great product.\nWhat\u0026rsquo;s Next? In our fast-paced development world (fortunately, the Java ecosystem is not as fast-paced as JavaScript), content ages and gets outdated over the years. New libraries, tools, and techniques pop up that make existing course lessons outdated.\nThat\u0026rsquo;s why I\u0026rsquo;m constantly trying to be up-to-date. As the testing topic is also the main focus area of my blog, that\u0026rsquo;s no problem. My freelance projects for clients also ensure I get enough hands-on experience.\nWhenever there\u0026rsquo;s something new or worth mentioning, I\u0026rsquo;ll add a new lesson to the course. If there\u0026rsquo;s something outdated, or I would do something different, I\u0026rsquo;ll replace a video.\nCompared to an eBook, keeping an online course up-to-date is more effort. There\u0026rsquo;s no search and replace functionality for already recorded videos. You have to find the correct spot and record a new video, or cut the outdated scene. But fortunately, in the area I\u0026rsquo;m creating content for, there\u0026rsquo;s maturity and stable APIs and libraries.\nSome course participants asked for a plain/text version of the online course to have a quick lookup reference for recipes and techniques. This is why I\u0026rsquo;m currently creating an eBook based on the online course.\nIt\u0026rsquo;s also a great way to attract a wider audience, as not everybody enjoys learning from videos and prefers to read a book on the beach.\nThe next online course is also waiting to be created. On top of the Stratospheric eBook (From Zero to Production with Spring Boot and AWS), which I\u0026rsquo;ve written with Tom Hombergs and Björn Wilmsmann, we\u0026rsquo;re creating an online course. Equipped with my insights from this course launch, I\u0026rsquo;m looking forward to this project.\nNow it\u0026rsquo;s your turn - go for it and let me know how it worked out!\nPS: If you plan to mirror this setup and have further questions, feel free to reach out.\nHappy a good one,\nPhil\n","permalink":"https://progmot.com/post/creating-and-selling-my-first-online-course/","summary":"A one-year retrospect after creating and selling my first online course: my strategy, the actual journey, mistakes, and recommendations.","title":"How I Made $35k Selling My First Online Course - A Retrospect"},{"content":"Hi \u0026#x1f44b;\nI\u0026rsquo;m Philip, a freelance IT consultant and Indie Hacker from \u0026#x1f1e9;\u0026#x1f1ea;.\nOn my main blog rieckpil I\u0026rsquo;m creating content under the slogan Testing Spring Boot Applications Made Simple with a focus on Java, Kotlin, Spring Boot, and AWS \u0026#x1f343;\nThis site acts as a meta blog for topics that don\u0026rsquo;t fit on a technical blog: freelancing, motivation, indie hacking, productivity, etc.\nI\u0026rsquo;ve co-authored Stratospheric - an eBook on getting started with Spring Boot on AWS (Amazon Web Services).\nTo demystify the name of this site:\nprogmot = Thoughts about programming \u0026amp; motivation\nEnjoy reading my random thoughts,\nPhilip\n","permalink":"https://progmot.com/about/","summary":"Hi \u0026#x1f44b;\nI\u0026rsquo;m Philip, a freelance IT consultant and Indie Hacker from \u0026#x1f1e9;\u0026#x1f1ea;.\nOn my main blog rieckpil I\u0026rsquo;m creating content under the slogan Testing Spring Boot Applications Made Simple with a focus on Java, Kotlin, Spring Boot, and AWS \u0026#x1f343;\nThis site acts as a meta blog for topics that don\u0026rsquo;t fit on a technical blog: freelancing, motivation, indie hacking, productivity, etc.\nI\u0026rsquo;ve co-authored Stratospheric - an eBook on getting started with Spring Boot on AWS (Amazon Web Services).","title":"About"},{"content":"Information pursuant to Sect. 5 German Telemedia Act (TMG) PragmaTech Digital Solutions Philip Riecks\nc/o WeWork Berlin\nWarschauer Pl. 11-13\n10245 Berlin\nContact E-mail: philip@progmot.com\nVAT ID Sales tax identification number according to Sect. 27 a of the Sales Tax Law: DE343982426\nPerson responsible for editorial Philip Riecks EU dispute resolution\nThe European Commission provides a platform for online dispute resolution (ODR): https://ec.europa.eu/consumers/odr/. Our e-mail address can be found above in the site notice.\nDispute resolution proceedings in front of a consumer arbitration board We are not willing or obliged to participate in dispute resolution proceedings in front of a consumer arbitration board.\n","permalink":"https://progmot.com/imprint/","summary":"Information pursuant to Sect. 5 German Telemedia Act (TMG) PragmaTech Digital Solutions Philip Riecks\nc/o WeWork Berlin\nWarschauer Pl. 11-13\n10245 Berlin\nContact E-mail: philip@progmot.com\nVAT ID Sales tax identification number according to Sect. 27 a of the Sales Tax Law: DE343982426\nPerson responsible for editorial Philip Riecks EU dispute resolution\nThe European Commission provides a platform for online dispute resolution (ODR): https://ec.europa.eu/consumers/odr/. Our e-mail address can be found above in the site notice.","title":"Imprint"},{"content":"1. An overview of data protection General information The following information will provide you with an easy to navigate overview of what will happen with your personal data when you visit this website. The term “personal data” comprises all data that can be used to personally identify you. For detailed information about the subject matter of data protection, please consult our Data Protection Declaration, which we have included beneath this copy.\nData recording on this website Who is the responsible party for the recording of data on this website (i.e., the “controller”)? The data on this website is processed by the operator of the website, whose contact information is available under section “Information about the responsible party (referred to as the “controller” in the GDPR)” in this Privacy Policy.\nHow do we record your data? We collect your data as a result of your sharing of your data with us. This may, for instance be information you enter into our contact form.\nOther data shall be recorded by our IT systems automatically or after you consent to its recording during your website visit. This data comprises primarily technical information (e.g., web browser, operating system, or time the site was accessed). This information is recorded automatically when you access this website.\nWhat are the purposes we use your data for? A portion of the information is generated to guarantee the error free provision of the website. Other data may be used to analyze your user patterns.\nWhat rights do you have as far as your information is concerned? You have the right to receive information about the source, recipients, and purposes of your archived personal data at any time without having to pay a fee for such disclosures. You also have the right to demand that your data are rectified or eradicated. If you have consented to data processing, you have the option to revoke this consent at any time, which shall affect all future data processing. Moreover, you have the right to demand that the processing of your data be restricted under certain circumstances. Furthermore, you have the right to log a complaint with the competent supervising agency.\nPlease do not hesitate to contact us at any time if you have questions about this or any other data protection related issues.\nAnalysis tools and tools provided by third parties There is a possibility that your browsing patterns will be statistically analyzed when your visit this website. Such analyses are performed primarily with what we refer to as analysis programs.\nFor detailed information about these analysis programs please consult our Data Protection Declaration below.\n2. Hosting External Hosting This website is hosted by an external service provider (host). Personal data collected on this website are stored on the servers of the host. These may include, but are not limited to, IP addresses, contact requests, metadata and communications, contract information, contact information, names, web page access, and other data generated through a web site.\nThe host is used for the purpose of fulfilling the contract with our potential and existing customers (Art. 6(1)(b) GDPR) and in the interest of secure, fast, and efficient provision of our online services by a professional provider (Art. 6(1)(f) GDPR).\nOur host will only process your data to the extent necessary to fulfil its performance obligations and to follow our instructions with respect to such data.\nWe are using the following host:\nNetlify, Inc. (\u0026ldquo;Netlify\u0026rdquo;), 2325 3rd Street, Suite 215, San Francisco, 94107 CA, USA\n3. General information and mandatory information Data protection The operators of this website and its pages take the protection of your personal data very seriously. Hence, we handle your personal data as confidential information and in compliance with the statutory data protection regulations and this Data Protection Declaration.\nWhenever you use this website, a variety of personal information will be collected. Personal data comprises data that can be used to personally identify you. This Data Protection Declaration explains which data we collect as well as the purposes we use this data for. It also explains how, and for which purpose the information is collected.\nWe herewith advise you that the transmission of data via the Internet (i.e., through e-mail communications) may be prone to security gaps. It is not possible to completely protect data against third-party access.\nInformation about the responsible party (referred to as the “controller” in the GDPR) The data processing controller on this website is:\nPragmaTech Digital Solutions Philip Riecks\nc/o WeWork Berlin\nWarschauer Pl. 11-13\n10245 Berlin\nE-mail: philip@progmot.com\nThe controller is the natural person or legal entity that single-handedly or jointly with others makes decisions as to the purposes of and resources for the processing of personal data (e.g., names, e-mail addresses, etc.).\nStorage duration Unless a more specific storage period has been specified in this privacy policy, your personal data will remain with us until the purpose for which it was collected no longer applies. If you assert a justified request for deletion or revoke your consent to data processing, your data will be deleted, unless we have other legally permissible reasons for storing your personal data (e.g., tax or commercial law retention periods); in the latter case, the deletion will take place after these reasons cease to apply.\nInformation on data transfer to the USA and other non-EU countries Among other things, we use tools of companies domiciled in the United States or other from a data protection perspective non-secure non-EU countries. If these tools are active, your personal data may potentially be transferred to these non-EU countries and may be processed there. We must point out that in these countries, a data protection level that is comparable to that in the EU cannot be guaranteed. For instance, U.S. enterprises are under a mandate to release personal data to the security agencies and you as the data subject do not have any litigation options to defend yourself in court. Hence, it cannot be ruled out that U.S. agencies (e.g., the Secret Service) may process, analyze, and permanently archive your personal data for surveillance purposes. We have no control over these processing activities.\nRevocation of your consent to the processing of data A wide range of data processing transactions are possible only subject to your express consent. You can also revoke at any time any consent you have already given us. This shall be without prejudice to the lawfulness of any data collection that occurred prior to your revocation.\nRight to object to the collection of data in special cases; right to object to direct advertising (Art. 21 GDPR) IN THE EVENT THAT DATA ARE PROCESSED ON THE BASIS OF ART. 6(1)(E) OR (F) GDPR, YOU HAVE THE RIGHT TO AT ANY TIME OBJECT TO THE PROCESSING OF YOUR PERSONAL DATA BASED ON GROUNDS ARISING FROM YOUR UNIQUE SITUATION. THIS ALSO APPLIES TO ANY PROFILING BASED ON THESE PROVISIONS. TO DETERMINE THE LEGAL BASIS, ON WHICH ANY PROCESSING OF DATA IS BASED, PLEASE CONSULT THIS DATA PROTECTION DECLARATION. IF YOU LOG AN OBJECTION, WE WILL NO LONGER PROCESS YOUR AFFECTED PERSONAL DATA, UNLESS WE ARE IN A POSITION TO PRESENT COMPELLING PROTECTION WORTHY GROUNDS FOR THE PROCESSING OF YOUR DATA, THAT OUTWEIGH YOUR INTERESTS, RIGHTS AND FREEDOMS OR IF THE PURPOSE OF THE PROCESSING IS THE CLAIMING, EXERCISING OR DEFENCE OF LEGAL ENTITLEMENTS (OBJECTION PURSUANT TO ART. 21(1) GDPR).\nIF YOUR PERSONAL DATA IS BEING PROCESSED IN ORDER TO ENGAGE IN DIRECT ADVERTISING, YOU HAVE THE RIGHT TO OBJECT TO THE PROCESSING OF YOUR AFFECTED PERSONAL DATA FOR THE PURPOSES OF SUCH ADVERTISING AT ANY TIME. THIS ALSO APPLIES TO PROFILING TO THE EXTENT THAT IT IS AFFILIATED WITH SUCH DIRECT ADVERTISING. IF YOU OBJECT, YOUR PERSONAL DATA WILL SUBSEQUENTLY NO LONGER BE USED FOR DIRECT ADVERTISING PURPOSES (OBJECTION PURSUANT TO ART. 21(2) GDPR).\nRight to log a complaint with the competent supervisory agency In the event of violations of the GDPR, data subjects are entitled to log a complaint with a supervisory agency, in particular in the member state where they usually maintain their domicile, place of work or at the place where the alleged violation occurred. The right to log a complaint is in effect regardless of any other administrative or court proceedings available as legal recourses.\nRight to data portability You have the right to demand that we hand over any data we automatically process on the basis of your consent or in order to fulfil a contract be handed over to you or a third party in a commonly used, machine readable format. If you should demand the direct transfer of the data to another controller, this will be done only if it is technically feasible.\nSSL and/or TLS encryption For security reasons and to protect the transmission of confidential content, such as purchase orders or inquiries you submit to us as the website operator, this website uses either an SSL or a TLS encryption program. You can recognize an encrypted connection by checking whether the address line of the browser switches from “http://” to “https://” and also by the appearance of the lock icon in the browser line.\nIf the SSL or TLS encryption is activated, data you transmit to us cannot be read by third parties.\nInformation about, rectification and eradication of data Within the scope of the applicable statutory provisions, you have the right to at any time demand information about your archived personal data, their source and recipients as well as the purpose of the processing of your data. You may also have a right to have your data rectified or eradicated. If you have questions about this subject matter or any other questions about personal data, please do not hesitate to contact us at any time.\nRight to demand processing restrictions You have the right to demand the imposition of restrictions as far as the processing of your personal data is concerned. To do so, you may contact us at any time. The right to demand restriction of processing applies in the following cases:\nIn the event that you should dispute the correctness of your data archived by us, we will usually need some time to verify this claim. During the time that this investigation is ongoing, you have the right to demand that we restrict the processing of your personal data. If the processing of your personal data was/is conducted in an unlawful manner, you have the option to demand the restriction of the processing of your data in lieu of demanding the eradication of this data. If we do not need your personal data any longer and you need it to exercise, defend or claim legal entitlements, you have the right to demand the restriction of the processing of your personal data instead of its eradication. If you have raised an objection pursuant to Art. 21(1) GDPR, your rights and our rights will have to be weighed against each other. As long as it has not been determined whose interests prevail, you have the right to demand a restriction of the processing of your personal data. If you have restricted the processing of your personal data, these data – with the exception of their archiving – may be processed only subject to your consent or to claim, exercise or defend legal entitlements or to protect the rights of other natural persons or legal entities or for important public interest reasons cited by the European Union or a member state of the EU.\n4. Recording of data on this website Cookies Our websites and pages use what the industry refers to as “cookies.” Cookies are small text files that do not cause any damage to your device. They are either stored temporarily for the duration of a session (session cookies) or they are permanently archived on your device (permanent cookies). Session cookies are automatically deleted once you terminate your visit. Permanent cookies remain archived on your device until you actively delete them, or they are automatically eradicated by your web browser.\nIn some cases, it is possible that third-party cookies are stored on your device once you enter our site (third-party cookies). These cookies enable you or us to take advantage of certain services offered by the third party (e.g., cookies for the processing of payment services).\nCookies have a variety of functions. Many cookies are technically essential since certain website functions would not work in the absence of the cookies (e.g., the shopping cart function or the display of videos). The purpose of other cookies may be the analysis of user patterns or the display of promotional messages.\nCookies, which are required for the performance of electronic communication transactions (required cookies) or for the provision of certain functions you want to use (functional cookies, e.g., for the shopping cart function) or those that are necessary for the optimization of the website (e.g., cookies that provide measurable insights into the web audience), shall be stored on the basis of Art. 6(1)(f) GDPR, unless a different legal basis is cited. The operator of the website has a legitimate interest in the storage of cookies to ensure the technically error free and optimized provision of the operator’s services. If your consent to the storage of the cookies has been requested, the respective cookies are stored exclusively on the basis of the consent obtained (Art. 6(1)(a) GDPR); this consent may be revoked at any time.\nYou have the option to set up your browser in such a manner that you will be notified any time cookies are placed and to permit the acceptance of cookies only in specific cases. You may also exclude the acceptance of cookies in certain cases or in general or activate the delete function for the automatic eradication of cookies when the browser closes. If cookies are deactivated, the functions of this website may be limited.\nIn the event that third-party cookies are used or if cookies are used for analytical purposes, we will separately notify you in conjunction with this Data Protection Policy and, if applicable, ask for your consent.\nServer log files The provider of this website and its pages automatically collects and stores information in so-called server log files, which your browser communicates to us automatically. The information comprises:\nThe type and version of browser used The used operating system Referrer URL The hostname of the accessing computer The time of the server inquiry The IP address This data is not merged with other data sources.\nThis data is recorded on the basis of Art. 6(1)(f) GDPR. The operator of the website has a legitimate interest in the technically error free depiction and the optimization of the operator’s website. In order to achieve this, server log files must be recorded.\n5. Analysis tools and advertising Matomo This website uses the open-source web analysis service Matomo. Matomo uses technologies that make it possible to recognize the user across multiple pages with the aim of analyzing the user patterns (e.g. cookies or device fingerprinting). The information recorded by Matomo about the use of this website will be stored on our server. Prior to archiving, the IP address will first be anonymized.\nThrough Matomo, we are able to collect and analyze data on the use of our website-by-website visitors. This enables us to find out, for instance, when which page views occurred and from which region they came. In addition, we collect various log files (e.g. IP address, referrer, browser, and operating system used) and can measure whether our website visitors perform certain actions (e.g. clicks, purchases, etc.).\nThe use of this analysis tool is based on Art. 6(1)(f) GDPR. The website operator has a legitimate interest in the analysis of user patterns, in order to optimize the operator’s web offerings and advertising. If appropriate consent has been obtained, the processing is carried out exclusively on the basis of Art. 6(1)(a) GDPR and § 25 (1) TTDSG, insofar the consent includes the storage of cookies or the access to information in the user’s end device (e.g., device fingerprinting) within the meaning of the TTDSG. This consent can be revoked at any time.\nIP anonymization For analysis with Matomo we use IP anonymization. Your IP address is shortened before the analysis, so that it is no longer clearly assignable to you.\nHosting We host Matomo exclusively on our own servers so that all analysis data remains with us and is not passed on.\n6. Online marketing and partner programs Affiliate Programs on this website The website operator participates in affiliate partner programs. If you click on a promotional ad on our website that participates in the partner program and subsequently engage in a transaction (e.g., a purchase), we will receive a commission from our affiliated partners. Hence, it is necessary that our affiliate partners can identify you and trace the fact that you were referred to the respective product through the promotional ad placed with us and that you have executed the predefined transaction. For this purpose, our affiliate partners use cookies or comparable recognition technology (e.g., device fingerprinting).\nData is stored and analyzed on the basis of Art. 6(1)(f) GDPR. The website operator has a legitimate interest in the correct computation of its affiliate compensation. If respective consent has been requested (e.g., consent to the storage of cookies), processing shall occur exclusively on the basis of Art. 6(1)(a) GDPR; the consent may be revoked at any time.\nWe participate in the following affiliate programs:\nAmazon partner program The provider is Amazon Europe Core S.à.r.l. For details, please consult Amazon’s Data Privacy Declaration at: https://www.amazon.de/gp/help/customer/display.html?nodeId=201909010.\nAdditional affiliate partner programs Vimeo\nMailchimp\nThrive Themes\nSendOwl Quaderno\n","permalink":"https://progmot.com/privacy-policy/","summary":"1. An overview of data protection General information The following information will provide you with an easy to navigate overview of what will happen with your personal data when you visit this website. The term “personal data” comprises all data that can be used to personally identify you. For detailed information about the subject matter of data protection, please consult our Data Protection Declaration, which we have included beneath this copy.","title":"Privacy Policy"},{"content":"I published my first article on Medium about a developer habit I started one year ago. To improve my personal development skills, I dedicated at least 30 minutes every day to code and learn something new. Looking back after 365 days, I can totally recommend it to everyone to take time out of the usual schedule to improve your skills.\nDeveloper Habit: Committing code to GitHub for 365 consecutive days My main motivation to start working on my skills every day was inspired by the following quote:\nProfessionals practice. True professionals work hard to keep their skills sharp and ready. It is not enough to simply do your daily job and call that practice.\nDoing your daily job is performance, not practice.\nPractice is when you specifically exercise your skills outside of the performance of your job for the sole purpose of refining and enhancing those skills. (The Clean Code, Page 19)\nFor a visual representation of my streak, I used the GitHub contribution view. This visual factor was really important as it helps to establish and proceed with a new habit, as you don\u0026rsquo;t want to lose your track.\nTL;DR for all impatient readers:\nDo it in themorning hours, you might be tired after work and you\u0026rsquo;ll start your day with an already achieved task Findinteresting andchallenging tasks to work on e.g. use online tutorials (Udemy, YouTube \u0026hellip;) and code with the instructor in parallel Stick to your decision and trackwhat you\u0026rsquo;ve already achieved Learn something new to become a generalist with one or more specialists (a better term for full-stack these days) Have fun while doing it otherwise it will be hard to stick to it Read the full article here.\nHave fun establishing your developer habits,\nPhil\n","permalink":"https://progmot.com/post/committing-code-to-github-for-365-consecutive-days/","summary":"I published my first article on Medium about a developer habit I started one year ago. To improve my personal development skills, I dedicated at least 30 minutes every day to code and learn something new. Looking back after 365 days, I can totally recommend it to everyone to take time out of the usual schedule to improve your skills.\nDeveloper Habit: Committing code to GitHub for 365 consecutive days My main motivation to start working on my skills every day was inspired by the following quote:","title":"Commiting to GitHub for 365 Consecutive Days"},{"content":"From the 19th to 21st of October 2018 the Hackathon Digital Tech Summit took place in Nuremberg as part of theDigital Festival in Nuremberg.\nWith more than 500 attendees and 23 Hackathon teams , it was my second and yet biggest Hackathon and my team made the first place .\nWe developed a solution for Siemens Healthineers to track their shipments of medical equipment so they are able to recognize possible damage and inform e.g. the receiving hospital and resend the same lifesaving equipment to prevent an outage.\nIn addition, the technicians were able to locate the shipment within a huge hospital to keep the seek time for the package as low as possible. In this blog post, I\u0026rsquo;ll write about the event and give you insights into our team and how we made the first place. Arriving at the event location\nThe whole event was organized by Zollhof a tech incubator in Nuremberg.\nThe main sponsors of this Hackathon were enterprises from the surrounding area like Adidas, Schaeffler, Siemens Healthineers, Nürnberger Versicherung and Gfk.\nThe enterprises provided challenges for the Hackathon in the following six tracks: Health, Sports, Retail, Security, Mobility \u0026amp; Wildcard.\nWithin every track, there were about up to four concrete challenges.\nThe event took place at the Lederer Kulturbrauerei in Nuremberg\nThe Hackathon started at 6 pm on Friday with a general welcome speech and presentation of the challenges. Every company got five minutes to pitch their challenge to the audience.\nAfter these pitches, the attendees voted by the show of hands in which track they\u0026rsquo;ll probably take part.\nEvery track then got a dedicated area within the event location to start a more detailed Q\u0026amp;A with the participants. Schaeffler pitching their challenge\nMy colleague and I were really convinced to take part in the challenge from Siemens Healthineers within the health track as they not only had an awesome pitch but they also had a lot of employees as mentors for the two days.\nThe main problem they addressed with their pitch was the fact that they ship a lot of critical and lifesaving technical equipment and don\u0026rsquo;t know the condition of the package until it arrives at the destination.\nShipping damaged medical equipment to not densely populated areas can lead to an outage of a device in the hospital and in the worst case to the death of people. To reduce this risk they were looking for solutions for this problem.\nThe first idea which came to our minds was a smart device that is able to collect different sensor data and perform actions (e.g. informing the hospital/Siemens/patients) when a package got damaged or will likely be broken when it arrives. For this idea, we were able to find and convince six other attendees to join our team PreTrack .\nOur mission was to save patients\u0026rsquo; lives with asmart tracking device for the shipment. Our team consisted of three rather business-related members and five techies. After the brainstorming session\nAt 10 pm on Friday, we were able to start our project and we began with brainstorming to find our concrete use case and discuss everyone\u0026rsquo;s ideas.\nWe agreed on developing a reusable device for the shipment which is able to send different sensor data to the cloud and trigger different actions and log every suspicious event during the shipping. In addition, our device should be able to locate the package within a huge hospital to find it more easily as the packages often arrive at night and the shift and the technician in the next morning don\u0026rsquo;t know where the required equipment is.\nWith this use case in mind, we split our tasks and our business started to figure out a possible business plan and gather more information about the logistics from Siemens employees. For the technical side, we had four major tasks:\nproviding a backend writing a user interface for our prototype retrieve and send sensor data from the device to the backend detecting damage from the sensor data. I took part in writing the backend service and managing our infrastructure.\nFor the hardware device, we picked a Pycom as these were provided during the Hackathon. In addition, we got access to AWS from Siemens and I created an EC2 instance for our backend and the webserver.\nFurthermore, I ordered a managed PostgreSQL within AWS to store our sensor data and the events. For managing our codebase we used a private repository on GitLab .\nWith the Pycom the programming language to access the sensor data was set to Python , for the backend I picked Java and Spring Boot , and for the frontend we chose Angular. After setting up the main infrastructure for our prototype and granting access to all our developers we all went home at 1 am.\nThe next day started at 8:30 AM with a short meeting with some Siemens employees to present our idea and get the first feedback . Until the afternoon we were able to send the first sensor data to our backend, store the data in our database.\nAfter the lunch, on Saturday we created a simple mockup for our prototype and while brainstorming for a mobile-friendly dashboard we got the idea to display a live view of the current alignment of the package. In the evening our prototype was able to stream the current sensor data to our frontend and with three.js we were able to visualize the alignment of the package with a small delay.\nOur business also gathered enough information during the whole day to start creating our slides for the pitch for the next day. This day ended at 12 pm as we were all really tired.\nSunday morning we integrated the business logic for detecting possible damage and in case of a drop /damage or shaking we sent events to our frontend application. As the semi-finals were announced for 4 pm we agreed on a code freeze at 3 pm to have enough time to practice our pitch.\nFor our pitch, we attached our Pycom to a sample package to show the functionality live. Team PreTrack after the semi-final\nFor the semi-finals, we pitched against three competitors in the health track which also took part in the challenge from Siemens. For our three minute pitch , we prepared a slide deck to explain our solution and used the two minutes for Q\u0026amp;A after the pitch to demonstrate the prototype in front of the jury. After a short discussion, we got the information from our mentors that we passed the semi-finals and are now part of the finals at 6 pm. We also got valuable feedback for our semi-final pitch as we focussed too much on the business side of our prototype and should have integrated our running solution within the three minute pitch time to prove the technical impressiveness of our prototype.\nWith this feedback, we restructured our slide deck and focussed more on the technical solution with a live demo right at the start of the pitch.\nFor our final pitch, we provided three smartphones and a laptop for the jury to prove that we are not simulating anything and they could see the alignment and the events live during the pitch.\nOur final pitch consisted of a short introduction to the problem , a live demo for dropping/damaging and shaking the shipment, a technical overview of our used technologies and an outlook for possible post-shipping use cases with the data we collect.\nThe final pitch After dinner, the five winning teams were announced and we were overwhelmed when the CEO of Zollhof Benjamin declared PreTrack as the winning team.\nThanks a lot to Zollhof for organizing this awesome event and Siemens Healthineers for providing the challenge and the support.\nSee you at the next Hackathon,\nPhil\n","permalink":"https://progmot.com/post/making-first-place-at-my-second-hackathon/","summary":"From the 19th to 21st of October 2018 the Hackathon Digital Tech Summit took place in Nuremberg as part of theDigital Festival in Nuremberg.\nWith more than 500 attendees and 23 Hackathon teams , it was my second and yet biggest Hackathon and my team made the first place .\nWe developed a solution for Siemens Healthineers to track their shipments of medical equipment so they are able to recognize possible damage and inform e.","title":"Making First Place at my Second Hackathon"},{"content":"From July 10th to the 11th I took part in the Hackathon HACK|BAY which was organized by the tech incubator Zollhof in Nuernberg. Even if I participated in several coding challenges and a company internal Hackathon, this was my first Hackathon with a jury and multiple competing teams.\nThe event was sponsored by several local companies and they presented challenges in the following topics: Connected City , Machine Learning , and Industrial IoT.\nEvery challenge got five minutes for presentation and afterward, we could form teams in free ideation. At first, I was really interested in the Industrial IoT challenge from Siemens where we could use their Mindsphere cloud environment to hack something for the production manager in the future.\nWhile we were talking to the presenter of the challenge my colleague and I couldn\u0026rsquo;t come up with a really innovative idea for this challenge.\nFortunately, a team from another challenge came to us and asked if there are some techies who don\u0026rsquo;t have a team yet. We followed them and they presented their current team and their idea. The challenge was from the insurance company HUK-Coburg in the Machine Learning topic.\nThe challenge was about \u0026ldquo;Scan and compare your insurance documents!\u0026rdquo; and they had already two business guys who were looking for techies for their team. The main idea was to use the vehicle registration document and use Machine Learning to speed up the time for a new insurance contract.\nWe liked the idea but my colleague and I both had not that deep knowledge in image recognition and OCR with Java but we decided on this challenge as we could learn a lot of new things.\nAfter the ideation phase, our final team consisted of six people (three business, three techies) and our team was calledSmart Insurance.\nTogether with our business teammates, we brainstormed about the desired outcome for the next 24 hours of hacking. Our business model was to provide an interface for insurance companies to upload the vehicle registration document for a potential new customer.\nAs a response, we would return all the required information for a new car insurance contract so that they can speed up the contract conclusion. We would be paid by everyAPI call of the insurance company and provide a trained AI algorithm to collect the data from the uploaded images.\nFor the Hackathon, we wanted to hack a prototype for the HUK-Coburg with a small web application to show the benefits with a real prototype.\nAs the German vehicle registration document has a defined structure we thought it would be easy to scan an image of it and to retrieve the data. But after some hours of trial and error with Tesseract for OCR and some image optimations we weren\u0026rsquo;t that happy with the result.\nFortunately, we found the Google Vision API and got quite better results with this OCR. Our \u0026ldquo;Machine Learning\u0026rdquo; algorithm just needed to retrieve the important data from the Google Vision API call.\nFor future development we would use a self-trained algorithm to do the OCR but in the short period of time, we just used Google.\nWith some tricks, we were able to get the address of the customer, the vehicle manufacturer and the vehicle type out of the registration document.\nWe used this data to call an API of the insurance company to calculate the insurance costs for exactly this car. As there are up to fifty parameters for an insurance contract we used a persona at age of 25 with about six years of driving experience to prefill some parameters for the API.\nOur technical architecture looked like the following (the Machine Learning algorithm was the Google Vision API plus some backend code for the showcase):\nAfter about 20 hours of hacking (including some sleep) our prototype was ready and we were able to get correct results in about 40% of the time if the vehicle document was printed correctly with no handwritten changes on it.\nFor the frontend technology we used Angular 6 and our backend was a Spring Boot application which I hosted on my server so that everybody could try the progressive web application on their smartphone:\nWhile we were hacking our business started to prepare our three-minute pitch in front of the jury. To make it to the finals we had to be a least second place in the semi-finals.\nNot all the twelve teams were pitching their ideas in a row. All three topics (Connected City , Machine Learning and Industrial IoT) had their semi-finals where the teams in this track competed against each other.\nFortunately, in our track we just had two competitors and made it through the semi-final.\nFor the final pitch, we had four competitors and got a new jury with executives from the sponsoring companies. Our idea and the web application convinced the jury and we gotthird place.\nThe winning team came up with a smart power socket solution and the second place was a plug-and-play Raspberry Pi network security solution for mid-sized companies.\nThe time spent hacking and our team was really nice. At first, we were quite doubtful if we can provide a solid solution for our challenge as we didn\u0026rsquo;t have any deeper knowledge of this topic, but we were amazed by our prototype and the result.\nI can recommend everyone to visit such events not only to win some prizes but to network and get together with awesome people. I\u0026rsquo;ll definitely participate again next year!\nHappy hacking,\nPhil\n","permalink":"https://progmot.com/post/my-first-hackathon/","summary":"From July 10th to the 11th I took part in the Hackathon HACK|BAY which was organized by the tech incubator Zollhof in Nuernberg. Even if I participated in several coding challenges and a company internal Hackathon, this was my first Hackathon with a jury and multiple competing teams.\nThe event was sponsored by several local companies and they presented challenges in the following topics: Connected City , Machine Learning , and Industrial IoT.","title":"My First Hackathon - HACK|BAY by ZOLLHOF"},{"content":"Today I want to inform you about one of my latest milestones as a software developer and convince you that you should do the same: Joining Stack Overflow to answer questions.\nAs a developer, you learn quite early to appreciate the support you get from Stack Overflow. Most of your daily coding problems can be solved with the help of this page.\nWhen I have a problem I normally grep the error code (if it exists) or try to explain my current issue and paste it into Google\u0026rsquo;s search bar. Nearly every time the top results are questions from Stack Overflow and most of the time they help me out of trouble (e.g. sometimes I forget on how to declare and initialize an array if I switch the programming language too often ).\nI think the following picture describes the use of Stack Overflow as a developer at its best:\nLast month I browsed through Stack Overflow to help solve one of my latest Spring Boot projects and I came across an open question about a problem with Spring MVC by chance. I had the answer to this problem at hand and I instantly decided to help this developer and therefore joined Stack Overflow.\nWhile answering this question I took time to give him a detailed answer and further links. In less than ten minutes I got informed that my answer could help him and that he is thankful for my help. Reading his answer I felt a kind of joy that I was able to help him and started to search for more Spring /Java related questions. At this time I even forgot my original intention (solving one of my Spring Boot problems) why I visited this page because I was in a kind of flow.\nA month since my registration at Stack Overflow has passed and the following resume sums up my experience with this awesome page.\nWhile using Stack Overflow the last years I recognized that there is a gamification system with reputation points and several medals but I did not understand the system behind it in detail. My first month gave me a deeper insight into this sophisticated system. As the community at Stack Overflow is mostly self-organized, the reputation points are used as an indicator of your knowledge and experience. You can earn them while asking a question, answering questions or editing questions.\nWith more reputation points you can break through several thresholds and are able to close duplicated questions for example. The medals are used as a kind of achievement bonus system and you get them through different interactions with this page.\nBenefits of answering questions on Stack Overflow During my three years as a developer, I always consumed the help of other developers at Stack Overflow and just used it for my own purposes. With the registration on this page, one of my main reasons was to give something back to the community. As a developer, you make use of so much Open Source tools/frameworks/projects and in my opinion, you should contribute to something and support other upcoming developers. I think the religious maxim:\nGiving is more blessed than taking\ncan also be applied to your behavior as a developer.\nWhile reading and answering to other developer\u0026rsquo;s problems you also gain the opportunity to improve your problem-solving capability and maybe prevent yourself from making the same mistake.\nWhat comes next is the benefit that you can prove and strengthen your knowledge about your programming language/favored framework or database. One of my central learnings during my student times was that if you are able to explain a concept/topic to another person/student and make them understand it, you truly understand the topic for yourself. In my opinion, this is the same with answering questions on Stack Overflow.\nAll in all, I think joining Stack Overflow is a so-called win-win situation for all participants and if you truly want to improve your skills you should join this community!\nAt the end I want to draw up a balance about my first-month @Stack Overflow:\nI \u0026hellip;\n\u0026hellip; earned ten bronze medals, \u0026hellip; asked one question and answered 35, \u0026hellip; got 319 reputation points, \u0026hellip; reached about 540 people, \u0026hellip; got 25 profile views, and answered questions about Spring and MongoDB most of the time Let\u0026rsquo;s see us on Stack Overflow!\nPhil.\n","permalink":"https://progmot.com/post/why-you-should-join-stackoverflow/","summary":"Today I want to inform you about one of my latest milestones as a software developer and convince you that you should do the same: Joining Stack Overflow to answer questions.\nAs a developer, you learn quite early to appreciate the support you get from Stack Overflow. Most of your daily coding problems can be solved with the help of this page.\nWhen I have a problem I normally grep the error code (if it exists) or try to explain my current issue and paste it into Google\u0026rsquo;s search bar.","title":"Why You Should Join Stack Overflow"},{"content":"From the 14th to the 16th of November I visited the Container Conf 2017 in Mannheim. This conference focussed on the Docker container technology and the ecosystem around Docker. In this blog post, I\u0026rsquo;ll summarize the top five pieces of advice I learned at this conference as a Summary of the Container Conf 2017.\nThe conference was structured into two parts: conference days and workshop days. On the 14th and the 17th of November, we were able to visit ten different full-day workshops about Kubernetes/Docker/DevOps/Microservices . From the 15th to 16th the conference days took place and about 650 attendees could learn from 60 technical talks about current topics on DevOps and containers.\nThe beginning keynote was held by Jennifer Davis (@sigje) with the topic: Swimming in Services: Navigating Unknown Waters. Besides that talk there were two more keynotes during the conference: One from the CTO of the N26 bank Patrick Kua and the other one from Brandon Philips the co-founder and CTO of CoreOS.\nLet\u0026rsquo;s now focus on the learnings of the Container Conf 2017\u0026hellip;\n1. Use EFK stack for handling logs in a Kubernetes cluster As it is quite cumbersome to analyze the log files of every deployed e.g. microservice in a Kubernetes cluster by hand, you should aggregate the logs of your application.\nTherefore a speaker presented the EFK (Elasticsearch , Fluentd , and Kibana ) stack.\nAs described in the Twelve-Factor App Manifesto your services should always log to stdout .\nWith an additional adapter for e.g. logback you can send your log messages to the logging layer provider Fluentd which will then distribute your logs to several output systems. With Fluentd you can define routes that e.g. your Apache Web server logs and the logs of your Spring Boot microservices are both distributed to Elasticsearch/AWS S3/MongoDB .\nA Fluentd config for the distribution of Spring Boot logs to Elasticsearch could look like the following:\n\u0026lt;source\u0026gt; @type forward port 24224 \u0026lt;/source\u0026gt; \u0026lt;match *.**\u0026gt; @type copy \u0026lt;store\u0026gt; @type elasticsearch host localhost port 9200 logstash_format true logstash_prefix fluentd logstash_dateformat %Y%m%d include_tag_key true type_name access_log tag_key @log_name flush_interval 1s \u0026lt;/store\u0026gt; \u0026lt;store\u0026gt; @type stdout \u0026lt;/store\u0026gt; \u0026lt;/match\u0026gt; In your microservices you can define the Fluentd appender quite easy in your logback.xml: XHTML\n\u0026lt;?xml version=\u0026#34;1.0\u0026#34; encoding=\u0026#34;UTF-8\u0026#34;?\u0026gt; \u0026lt;configuration\u0026gt; \u0026lt;include resource=\u0026#34;org/springframework/boot/logging/logback/base.xml\u0026#34; /\u0026gt; \u0026lt;property name=\u0026#34;FLUENTD_HOST\u0026#34; value=\u0026#34;127.0.0.1\u0026#34; /\u0026gt; \u0026lt;property name=\u0026#34;FLUENTD_PORT\u0026#34; value=\u0026#34;24224\u0026#34; /\u0026gt; \u0026lt;appender name=\u0026#34;FLUENT\u0026#34; class=\u0026#34;ch.qos.logback.more.appenders.DataFluentAppender\u0026#34;\u0026gt; \u0026lt;tag\u0026gt;fluentd\u0026lt;/tag\u0026gt; \u0026lt;label\u0026gt;test\u0026lt;/label\u0026gt; \u0026lt;remoteHost\u0026gt;${FLUENTD_HOST}\u0026lt;/remoteHost\u0026gt; \u0026lt;port\u0026gt;${FLUENTD_PORT}\u0026lt;/port\u0026gt; \u0026lt;maxQueueSize\u0026gt;20\u0026lt;/maxQueueSize\u0026gt; \u0026lt;/appender\u0026gt; \u0026lt;logger name=\u0026#34;de.rieckpil\u0026#34; level=\u0026#34;info\u0026#34; additivity=\u0026#34;false\u0026#34;\u0026gt; \u0026lt;appender-ref ref=\u0026#34;CONSOLE\u0026#34; /\u0026gt; \u0026lt;appender-ref ref=\u0026#34;FILE\u0026#34; /\u0026gt; \u0026lt;appender-ref ref=\u0026#34;FLUENT\u0026#34; /\u0026gt; \u0026lt;/logger\u0026gt; \u0026lt;/configuration\u0026gt; With Kibana you can now visualize the logs, build dashboards for your logs and search for bugs in a centralized system without manual work.\n2. Gradle as Java build tool We all know Maven as a build tool for Java and some of you might have seen a Gradle option when you try to import a new library for your Java project.\nAs Maven is always displayed as the first option for dependency management I realized that there are other build tools like Gradle but I never looked at these build tools.\nDifferent speakers at the conference recommended Gradle and one talk was dedicated to the latest innovations in Gradle. With Gradle , you won\u0026rsquo;t write any pom.xml but now build.gradle and settings.gradle files. These files are structured straightforward and written in either Groovy or Kotlin.\nAn example build.gradle file for a small Spring Boot app could look like the following: Java\nbuildscript { ext { springBootVersion = \u0026#39;1.5.8.RELEASE\u0026#39; } repositories { mavenCentral() } dependencies { classpath(\u0026#34;org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}\u0026#34;) } } apply plugin: \u0026#39;java\u0026#39; apply plugin: \u0026#39;org.springframework.boot\u0026#39; repositories { mavenCentral() } dependencies { compile(\u0026#34;org.springframework.boot:spring-boot-starter-web\u0026#34;) testCompile(\u0026#34;junit:junit\u0026#34;) } The most convincing fact about Gradle for me was that Maven had eight releases since 2005 and Gradle released a new version 35 times since 2012. Furthermore, the speakers mentioned the following pros of using Gradle:\nincremental builds reduced build script complexity integrated build cache (only local changes that don\u0026rsquo;t build yet, are compiled) Google uses it for it\u0026rsquo;s Android development For the next projects, I will use Gradle instead of Maven and inform you about my experience in the near future.\nFurthermore, the speaker mentioned that Java developers should definitely have a look at the programming language Kotlin.\n3. Serverless computing With serverless computing, you just write plain functions that are triggered by an API-Gateway or an event. Therefore you just have to pay for each function call and won\u0026rsquo;t have pay for the idle time.\nThe speaker used AWS Lambda as a cloud service from Amazon for deploying a lambda function. He played around a bit with these functions and presented his experiences.\nFor one of his Java examples, he mentioned that for a \u0026ldquo;cold-start\u0026rdquo; of a lambda function a containerized JVM is launched which will cost time and this JVM should be held \u0026ldquo;alive\u0026rdquo; with to avoid this problem for further lambda calls.\nA possible use case for these lambda functions could be an image processing function that will create a thumbnail out of an uploaded user image and store it e.g. to an S3 bucket. Eberhard Wolff, for example, uses lambda functions for an automatic response for one of his mail accounts to send the conference slides directly to a requesting attendee.\nFor a more complex application like microservice system architecture, it is quite difficult to debug the serverless application and test it.\n4. Adding security checks to your build pipeline In the interesting talk with the topic Left Shift Cybersecurity the two speakers explained their experience with security issues of their Java applications. They work for a security company and among other things they have pen-testers that manually check the security and robustness of their client\u0026rsquo;s application. As there are always the same basic security issues with web applications like XSS and SQL injections they wanted to statically find these \u0026ldquo;low hanging fruits\u0026rdquo; in a build pipeline to enable their pen-testers to concentrate on more complex issues.\nThey presented both commercial and open-source Java libraries for this task. For a dependency vulnerability check, they showed an example with the DependencyCheck.\nWhile using open-source tools for this task they called attention to analyze the generated reports with caution. The security databases might not always be up-to-date and some tools mix up some dependencies. A Commercial library is for example Snyk.\nAnother check was the static code analysis check with the tool FindBugs which can be integrated into the build pipeline and generate reports (other tools they mentioned: Veracode and Checkmarkx). Here again, it is important to not blindly trust the results of this check because there are also some code elements which will be reported as \u0026ldquo;bugs\u0026rdquo; but are wanted.\nHe used an example with the @RequestMapping() annotation in Spring Boot which publishes an endpoint and was marked as \u0026ldquo;insecure\u0026rdquo;. Strangely enough, @GetMapping() was not reported as a \u0026ldquo;bug\u0026rdquo;.\nFor more dynamic security checks they showed an example with ZAP Proxy. With this tool, they were able to detect an XSS and a SQL injection issue during their build.\nTo sum the talk up they recommended to use this kind of static security check but do not depend on the success of your build on these checks as you should always analyze the generated reports twice.\n5. Prometheus and Grafana Besides the EFK stack for aggregating application logs in a Kubernetes cluster, you also want to have live monitoring of your system/application/host metrics.\nFor this task, the open-source solution Prometheus in addition to Grafana are currently de facto standards for collecting and visualizing metrics. Both Prometheus and Grafana can be integrated into the Kubernetes cluster.\nThe most common host metrics (e.g. CPU, disk, RAM, network\u0026hellip;) are gathered with the node-exporter from Prometheus. In addition, you can collect metrics about the container resource metrics with the cAdvisor.\nWith the simpleclient as a Java dependency your application is able to publish internal Java metrics for Prometheus (e.g. time calculation, call hierarchies \u0026hellip;).\nSpring got an own library called simpleclient_spring_web to use an AOP collector which is able for example to measure the duration of a method with the @PrometheusTimeMethod() annotation.\nMoreover, there are some extensions for tracking database\u0026rsquo; metrics to monitor for example the elapsed time of a REST request in every part of your backend.\nI hope you liked the Summary of the Container Conf 2017!\ndocker stop summarizing-conference-service\n","permalink":"https://progmot.com/post/summary-of-the-container-conf-2017/","summary":"From the 14th to the 16th of November I visited the Container Conf 2017 in Mannheim. This conference focussed on the Docker container technology and the ecosystem around Docker. In this blog post, I\u0026rsquo;ll summarize the top five pieces of advice I learned at this conference as a Summary of the Container Conf 2017.\nThe conference was structured into two parts: conference days and workshop days. On the 14th and the 17th of November, we were able to visit ten different full-day workshops about Kubernetes/Docker/DevOps/Microservices .","title":"Summary of the Container Conf 2017"}]