{"openapi":"3.1.0","info":{"title":"Medium API","version":"1.0.0","description":"Read Medium posts in real time — no login or key needed. Pull the recent stories of any Medium user (@handle), any topic/tag, or any publication, straight from Medium's own public RSS feeds. Each post comes with its title, author, canonical link, publish date, categories/tags, a clean text excerpt and the full content HTML. Pass user = the @handle, tag = a topic slug, or publication = a publication slug; every call is live (no cache). 4 endpoints. Built for content aggregation, author/topic monitoring and reading-list back-ends. A Medium reader API. No upstream key, no cache.","contact":{"name":"PremiumApi","url":"https://www.oanor.com/by/premiumapi"}},"servers":[{"url":"https://api.oanor.com/medium-api","description":"oanor gateway"}],"tags":[{"name":"Medium"},{"name":"Meta"}],"components":{"securitySchemes":{"oanorKey":{"type":"apiKey","in":"header","name":"x-oanor-key","description":"Get your key at https://www.oanor.com/developer/keys"}}},"security":[{"oanorKey":[]}],"paths":{"/v1/publication":{"get":{"operationId":"get_v1_publication","tags":["Medium"],"summary":"Publication posts","description":"","parameters":[{"name":"publication","in":"query","required":true,"description":"Publication slug","schema":{"type":"string"},"example":"better-programming"}],"security":[{"oanorKey":[]}],"responses":{"200":{"description":"OK","content":{"application/json":{"example":{"data":{"feed":{"link":"https://betterprogramming.pub?source=rss----d0b105d10f0a---4","image":"https://cdn-images-1.medium.com/proxy/1*TGH72Nnw24QL3iV9IOm4VA.png","title":"Better Programming - Medium","description":"Advice for programmers. - Medium"},"count":10,"items":[{"guid":"https://medium.com/p/bf37baef8f27","link":"https://medium.com/better-programming/let-a-thousand-programming-publications-bloom-bf37baef8f27?source=rss----d0b105d10f0a---4","title":"Let a thousand programming publications bloom.","author":"Tony Stubblebine","excerpt":"I’m putting Better Programming on hiatus to make room for other programming publications. I get that this is a big pivot given that we switched to a new editor recently. But things are changing at Medium and I think this will ultimately be a boon for everyone, authors, readers and publications. I wo","updated":"2023-11-27T17:53:37.557Z","published":"Fri, 10 Nov 2023 18:18:10 GMT","categories":[],"content_html":"<h4>I’m putting Better Programming on hiatus to make room for other programming publications.</h4><p>I<em> get that this is a big pivot given that we switched to a new editor recently. But things are changing at Medium and I think this will ultimately be a boon for everyone, authors, readers and publications.</em></p><p>I would like to inspire some (but not all) of you to start a publication and give you some guidelines on how to do it well. If you are an author, there are many other publications to write for and hopefully there will soon be even more (check the comments for suggestions).</p><p>Medium has always had publications that acted as something in between a group blog and a sub-reddit. Publication editors help set a quality bar, give feedback on your posts, and bring you an audience. Publications are a pillar of the Medium experience.</p><p>But the publication opportunities that (I think) are exciting are changing. In the past, the way to have a successful publication was to publish on anything and everything. So Medium was dominated by broad, high volume publications. Better Programming was one of those pubs and we published on topics that might not have a lot of overlapping readers. How many of you are currently programming in all of these languages: Go, Rust, Javascript, Ruby, Python, Swift, Kotlin, and Dart?</p><p>Better Programming has published stories on all of those topics and more, and so by definition we were often publishing stories that a lot of you don’t want to read. The direction Medium is heading is to optimize for publications that are more focused than Better Programming has been.</p><p>There are two types of focuses that I’m personally excited about. One is that publications are de facto communities of enthusiasts. The other is that publications bring a level of expertise to Medium’s boost program. <em>Caveat: these are just what I’m excited about — maybe you have more creative ideas than I do.</em></p><p>Both cases beg for publications that are focused.</p><p>If you want to build an enthusiast community of people who love Kotlin, who want to write about their Kotlin projects and what they are learning, then you don’t also need authors in your publication who are writing about Swift.</p><p>Similarly, Medium is leaning on the expertise of publication editors to contribute as nominators in the Boost program. It’s hard to bring credible expertise when your focus is too broad. Most nominators also have first hand expertise beyond what they publish. So, if I were to run Better Programming myself, I think I could credibly nominate within Rails (I’ve built several companies on that stack) and Regular Expressions (I wrote a book), but I’m clueless on nearly everything else.</p><p>Running a publication isn’t for everyone and it isn’t a get-rich-quick scheme. The best publications are run out of authentic interest in a topic and nothing more. In technical topics, there can be some financial rewards, which I’ll get to. But mainly it’s best to think of this as a way to harness a passion you may have. I know that the community building impulse is strong in many of you because I’ve seen how many people have started publications on Medium over the years.</p><p>For any of you who are interested, I’m going to give you some tips on starting a publication. These aren’t exactly a recipe, but I’ll try to arrange them in order.</p><ol><li>Pubs are easy to start and at minimum you have yourself as a possible author to fill the pub with stories. <a href=\"https://medium.com/new-publication\">Here’s a link to get going</a>.</li><li>If you want to accept other authors then you need to setup instructions. Almost all publications that accept other authors setup a “write for us” page with instructions, make it a tab on the publication, write a style guide, and then create a Google form to handle new author applications. <a href=\"https://betterprogramming.pub/write-for-us-5c4bcba59397\">Copy ours</a>.</li><li>Do you want to focus on inclusivity? If so, then your role is probably more about support and encouragement and less about setting a high editorial bar. People get squeamish about being judged but the thing I’ve long recognized is that all writing was useful to the writer and is often useful to at least a few people, but very little writing is going to trend on Reddit or HackerNews.</li><li>Do you want to focus on exclusivity, i.e. finding the best of the best ideas and information on a topic? Medium’s Boost program gives publication editors a tool to recruit authors: “I can help boost your stories to more readers.” You can’t just boost anything, it has to be the best of the best. And so focusing on that is a very exclusive approach. I often think of a publication here about Runners where the editor is using his access to the Boost to work with professional running coaches, professional runners, and the former editor-in-chief of Runners World. That must be so fun for him! The programming equivalent is different for each programming languange so I’ll use an example from the language I got started in: if I started a publication for Perl, I’d use the boost as a way to recruit Larry Wall.</li><li>Consider becoming a Boost nominator but also consider that doing that will require having a strong nose for the best of the best. Of course every story on Medium is “high quality” but there are certain stories that are important, accurate, helpful and maybe even more than that. This isn’t official policy, but unofficially, it would be reasonable to <a href=\"https://blog.medium.com/a-nosy-faq-about-nominating-stories-for-our-boost-44bbf79549c\">submit an application to be a Boost Nominator</a> once you have a publication with three authors and ten stories.</li><li>Getting a publication started requires recruiting authors. Hopefully you know some already, even if they aren’t on Medium. I think that if you don’t know a subject well enough that you also already know other people with similar enthusiasm and expertise in that subject, then starting a publication isn’t for you. That’s not a hard rule, but I’m saying it from experience. After recruiting from your own network, the way almost every other publication has recruited authors is by monitoring relevant tags on Medium and then using the private note feature to invite recently published stories into your publication.</li><li>Lets talk money. If you are a publication that Boosts stories you will get paid an honorarium. Plus if you build an audience, your own stories might make more money. But, you are missing the big picture if this is the most important thing to you. Writing and editing is a form of portfolio building. The software engineering field pays so much money, way beyond what Medium pays for writing. So focusing on getting paid from Medium is the ultimate example of a local maxima because the you can make 1000x more by building a reputation and using it to get a job or raise. This is just fact.</li></ol><p>If you do start a programming publication that is looking for authors or you’ve already started a programming publication like that, post a link in the responses along with a link to your submission guidelines.</p><p>Authors: I looked up Better Programming’s stats. 4.6k authors have published 16.8k stories to Better Programming. Those stories generated 151M page views. Not all of them were behind the paywall, but the ones that were earned authors $999 thousand dollars. It’s been a huge honor to play a role in that and my thanks go out to the editors who’ve made it happen and to all of you for writing. Medium is still a great home for you, it’s just that you should find new places to publish.</p><figure><img alt=\"\" src=\"https://cdn-images-1.medium.com/max/1024/1*tKikPWjE4MZ5WgdfZuyvEg.png\" /></figure><img src=\"https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=bf37baef8f27\" width=\"1\" height=\"1\" alt=\"\"><hr><p><a href=\"https://medium.com/better-programming/let-a-thousand-programming-publications-bloom-bf37baef8f27\">Let a thousand programming publications bloom.</a> was originally published in <a href=\"https://betterprogramming.pub\">Better Programming</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>"},{"guid":"https://medium.com/p/3f456a51ff99","link":"https://medium.com/better-programming/calling-aws-bedrock-from-code-3f456a51ff99?source=rss----d0b105d10f0a---4","title":"Calling AWS Bedrock from code","author":"Thomas Reid","updated":"2023-11-10T17:35:02.467Z","published":"Fri, 10 Nov 2023 17:35:02 GMT","categories":["bedrock","python","llm","boto3","ai"]},{"guid":"https://medium.com/p/3e51432ae0e9","link":"https://medium.com/better-programming/pandas-v-psycopg-a-postgres-database-speed-test-who-wins-3e51432ae0e9?source=rss----d0b105d10f0a---4","title":"Pandas v Psycopg:","author":"Thomas Reid","updated":"2023-11-10T17:34:53.793Z","published":"Fri, 10 Nov 2023 17:34:53 GMT","categories":["speed-test","psycopg2","postgres","performance","pandas"]},{"guid":"https://medium.com/p/e1f66a3b0530","link":"https://medium.com/better-programming/automating-your-devops-writing-scripts-that-save-time-and-headaches-e1f66a3b0530?source=rss----d0b105d10f0a---4","title":"Automating Your DevOps: Writing Scripts that Save Time and Headaches","author":"Ulas Can Cengiz","updated":"2023-11-10T17:34:20.767Z","published":"Fri, 10 Nov 2023 17:34:20 GMT","categories":["software-development","development","devops","engineering","automation"]},{"guid":"https://medium.com/p/c5f79fc8019e","link":"https://medium.com/better-programming/integrating-psychology-into-software-development-c5f79fc8019e?source=rss----d0b105d10f0a---4","title":"Integrating Psychology into Software Development","author":"Ulas Can Cengiz","updated":"2023-11-10T17:34:07.833Z","published":"Fri, 10 Nov 2023 17:34:07 GMT","categories":["engineering","architecture","software-design","software-development","psychology"]},{"guid":"https://medium.com/p/ccbd1d3f9fd7","link":"https://medium.com/better-programming/gpt-function-calling-5-underrated-use-cases-ccbd1d3f9fd7?source=rss----d0b105d10f0a---4","title":"GPT Function Calling: 5 Underrated Use Cases","author":"Max Brodeur-Urbas","excerpt":"OpenAI’s backend converting messy unstructured data to structured data via functions OpenAI’s “Function Calling” might be the most groundbreaking yet under appreciated feature released by any software company… ever. What are GPT Functions Functions allow you to turn unstructured data into structured","updated":"2023-11-20T20:55:28.826Z","published":"Fri, 10 Nov 2023 17:33:58 GMT","categories":["automation","llm","gpt","chatgpt","openai"],"content_html":"<figure><img alt=\"\" src=\"https://cdn-images-1.medium.com/max/1024/1*doghMb44J43LgPYtkUCByw.jpeg\" /><figcaption>OpenAI’s backend converting messy unstructured data to structured data via functions</figcaption></figure><p>OpenAI’s “Function Calling” might be the most groundbreaking yet under appreciated feature released by any software company… ever.</p><h3>What are GPT Functions</h3><p>Functions allow you to <strong>turn unstructured data into structured data</strong>. This might not sound all that groundbreaking but when you consider that 90% of data processing and data entry jobs worldwide exist for this exact reason, it’s quite a revolutionary feature that went somewhat unnoticed.</p><p>Have you ever found yourself <em>begging</em> GPT (3.5 or 4) to spit out the answer you want and absolutely nothing else? No “Sure, here is your…” or any other useless fluff surrounding the core answer. GPT Functions are the solution you’ve been looking for.</p><h4>How are Functions meant to work?</h4><blockquote>OpenAI’s docs on function calling are extremely limited. You’ll find yourself digging through their developer forum for examples of how to use them. I dug around the forum for you and have many example coming up.</blockquote><p>Here’s one of the only examples you’ll be able to find in their docs:</p><pre>functions = [<br>        {<br>            &quot;name&quot;: &quot;get_current_weather&quot;,<br>            &quot;description&quot;: &quot;Get the current weather in a given location&quot;,<br>            &quot;parameters&quot;: {<br>                &quot;type&quot;: &quot;object&quot;,<br>                &quot;properties&quot;: {<br>                    &quot;location&quot;: {<br>                        &quot;type&quot;: &quot;string&quot;,<br>                        &quot;description&quot;: &quot;The city and state, e.g. San Francisco, CA&quot;,<br>                    },<br>                    &quot;unit&quot;: {&quot;type&quot;: &quot;string&quot;, &quot;enum&quot;: [&quot;celsius&quot;, &quot;fahrenheit&quot;]},<br>                },<br>                &quot;required&quot;: [&quot;location&quot;],<br>            },<br>        }<br>    ]</pre><p>A function definition is a rigid JSON format that defines a function name, description and parameters. In this case, the function is meant to get the current weather. Obviously GPT isn’t able to call this actual API (since it doesn’t exist) but using this structured response you’d be able to connect the real API hypothetically.</p><p>At a high level however, functions provide two layers of inference:</p><h4>Picking the function itself:</h4><p>You may notice that functions are passed into the OpenAI API call as an array. The reason you provide a name and description to each function are so GPT can decide which to use based on a given prompt. Providing multiple functions in your API call is like giving GPT a Swiss army knife and asking it to cut a piece of wood in half. It knows that even though it has a pair of pliers, scissors and a knife, it should use the saw!</p><p><strong>Function definitions contribute towards your token count</strong>. Passing in hundreds of functions would not only take up the majority of your token limit but also result in a drop in response quality. I often don’t even use this feature and only pass in 1 function that I force it to use. It is very nice to have in certain use cases however.</p><h4>Picking the parameter values based on a prompt:</h4><p>This is the real magic in my opinion. GPT being able to choose the tool in it’s tool kit is amazing and definitely the focus of their feature announcement but I think this applies to more use cases.</p><p><strong>You can imagine a function like handing GPT a form to fill out</strong>. <strong>It uses its reasoning, the context of the situation and field names/descriptions to decide how it will fill out each field.</strong> Designing the form and the additional information you pass in is where you can get creative.</p><figure><img alt=\"\" src=\"https://cdn-images-1.medium.com/max/1020/1*YZEdqYdzo_LyCSK2YzQDrQ.png\" /><figcaption>GPT filling out your custom form (function parameters)</figcaption></figure><h3>5 Useful Applications</h3><h3>Data Extraction</h3><p>One of the most common things I use functions for to extract specific values from a large chunk of text. The sender’s address from an email, a founders name from a blog post, a phone number from a landing page.</p><p>I like to imagine I’m searching for a needle in a haystack except the LLM burns the haystack, leaving nothing but the needle(s).</p><figure><img alt=\"\" src=\"https://cdn-images-1.medium.com/max/1023/1*nycFdIgLvj_RVyQ_J28r9A.png\" /><figcaption>GPT Data Extraction Personified.</figcaption></figure><h4>Use case: Processing thousands of contest submissions</h4><p>I built an automation that iterated over thousands of contest submissions. Before storing these in a Google sheet I wanted to extract the email associated with the submission. Heres the function call I used for extracting their email.</p><pre>{<br>   &quot;name&quot;:&quot;update_email&quot;,<br>   &quot;description&quot;:&quot;Updates email based on the content of their submission.&quot;,<br>   &quot;parameters&quot;:{<br>      &quot;type&quot;:&quot;object&quot;,<br>      &quot;properties&quot;:{<br>         &quot;email&quot;:{<br>            &quot;type&quot;:&quot;string&quot;,<br>            &quot;description&quot;:&quot;The email provided in the submission&quot;<br>         }<br>      },<br>      &quot;required&quot;:[<br>         &quot;email&quot;<br>      ]<br>   }<br>}</pre><h3>Scoring</h3><p>Assigning unstructured data a score based on dynamic, natural language criteria is a wonderful use case for functions. You could score comments during sentiment analysis, essays based on a custom grading rubric, a loan application for risk based on key factors. A recent use case I applied scoring to was scoring of sales leads from 0–100 based on their viability.</p><h4>Use Case: Scoring Sales leads</h4><p>We had hundreds of prospective leads in a single google sheet a few months ago that we wanted to tackle from most to least important. Each lead contained info like company size, contact name, position, industry etc.</p><p>Using the following function we scored each lead from 0–100 based on our needs and then sorted them from best to worst.</p><pre>{<br>   &quot;name&quot;:&quot;update_sales_lead_value_score&quot;,<br>   &quot;description&quot;:&quot;Updates the score of a sales lead and provides a justification&quot;,<br>   &quot;parameters&quot;:{<br>      &quot;type&quot;:&quot;object&quot;,<br>      &quot;properties&quot;:{<br>         &quot;sales_lead_value_score&quot;:{<br>            &quot;type&quot;:&quot;number&quot;,<br>            &quot;description&quot;:&quot;An integer value ranging from 0 to 100 that represents the quality of a sales lead based on these criteria. 100 is a perfect lead, 0 is terrible. Ideal Lead Criteria:\\n- Medium sized companies (300-500 employees is the best range)\\n- Companies in primary resource heavy industries are best, ex. manufacturing, agriculture, etc. (this is the most important criteria)\\n- The higher up the contact position, the better. VP or Executive level is preferred.&quot;<br>         },<br>         &quot;score_justification&quot;:{<br>            &quot;type&quot;:&quot;string&quot;,<br>            &quot;description&quot;:&quot;A clear and conscise justification for the score provided based on the custom criteria&quot;<br>         }<br>      }<br>   },<br>   &quot;required&quot;:[<br>      &quot;sales_lead_value_score&quot;, <br>      &quot;score_justification&quot;<br>   ]<br>}</pre><h3>Categorization:</h3><p>Define custom buckets and have GPT thoughtfully consider each piece of data you give it and place it in the correct bucket. This can be used for labelling tasks like selecting the category of youtube videos or for discrete scoring tasks like assigning letter grades to homework assignments.</p><h4><strong>Use Case: Labelling news articles.</strong></h4><p>A very common first step in data processing workflows is separating incoming data into different streams. A recent automation I built did exactly this with news articles scraped from the web. I wanted to sort them based on the topic of the article and include a justification for the decision once again. Here’s the function I used:</p><pre>{<br>   &quot;name&quot;:&quot;categorize&quot;,<br>   &quot;description&quot;:&quot;Categorize the input data into user defined buckets.&quot;,<br>   &quot;parameters&quot;:{<br>      &quot;type&quot;:&quot;object&quot;,<br>      &quot;properties&quot;:{<br>         &quot;category&quot;:{<br>            &quot;type&quot;:&quot;string&quot;,<br>            &quot;enum&quot;:[<br>               &quot;US Politics&quot;,<br>               &quot;Pandemic&quot;,<br>               &quot;Economy&quot;,<br>               &quot;Pop culture&quot;,<br>               &quot;Other&quot;<br>            ],<br>            &quot;description&quot;:&quot;US Politics: Related to US politics or US politicians, Pandemic: Related to the Coronavirus Pandemix, Economy: Related to the economy of a specific country or the world. , Pop culture: Related to pop culture, celebrity media or entertainment., Other: Doesn&#39;t fit in any of the defined categories. &quot;<br>         },<br>         &quot;justification&quot;:{<br>            &quot;type&quot;:&quot;string&quot;,<br>            &quot;description&quot;:&quot;A short justification explaining why the input data was categorized into the selected category.&quot;<br>         }<br>      },<br>      &quot;required&quot;:[<br>         &quot;category&quot;,<br>         &quot;justification&quot;<br>      ]<br>   }<br>}</pre><h3>Option-Selection:</h3><p>Often times when processing data, I give GPT many possible options and want it to select the best one based on my needs. I only want the value it selected, no surrounding fluff or additional thoughts. Functions are perfect for this.</p><h4>Use Case: Finding the “most interesting AI news story” from hacker news</h4><blockquote>I wrote another <a href=\"https://medium.com/better-programming/building-an-autonomous-twitter-account-with-llms-de53f5e519ba\">medium article here</a> about how I automated my entire Twitter account with GPT. Part of that process involves selecting the most relevant posts from the front pages of hacker news. This post selection step leverages functions!</blockquote><p>To summarize the functions portion of the use case, we would scrape the first n pages of hacker news and ask GPT to select the post most relevant to “AI news or tech news”. GPT would return only the headline and the link selected via functions so that I could go on to scrape that website and generate a tweet from it.</p><p>I would pass in the user defined query as part of the message and use the following function definition:</p><pre>{<br>   &quot;name&quot;:&quot;find_best_post&quot;,<br>   &quot;description&quot;:&quot;Determine the best post that most closely reflects the query.&quot;,<br>   &quot;parameters&quot;:{<br>      &quot;type&quot;:&quot;object&quot;,<br>      &quot;properties&quot;:{<br>         &quot;best_post_title&quot;:{<br>            &quot;type&quot;:&quot;string&quot;,<br>            &quot;description&quot;:&quot;The title of the post that most closely reflects the query, stated exactly as it appears in the list of titles.&quot;<br>         }<br>      },<br>      &quot;required&quot;:[<br>         &quot;best_post_title&quot;<br>      ]<br>   }<br>}</pre><h3>Filtering:</h3><p>Filtering is a subset of categorization where you categorize items as either true or false based on a natural language condition. A condition like “is Spanish” will be able to filter out all Spanish comments, articles etc. using a simple function and conditional statement immediately after.</p><h4>Use Case: Filtering contest submission</h4><p>The same automation that I mentioned in the “Data Extraction” section used ai-powered-filtering to weed out contest submissions that didn’t meet the deal-breaking criteria. Things like “must use typescript” were absolutely mandatory for the coding contest at hand. We used functions to filter out submissions and trim down the total set being processed by 90%. Here is the function definition we used.</p><pre>{<br>   &quot;name&quot;:&quot;apply_condition&quot;,<br>   &quot;description&quot;:&quot;Used to decide whether the input meets the user provided condition.&quot;,<br>   &quot;parameters&quot;:{<br>      &quot;type&quot;:&quot;object&quot;,<br>      &quot;properties&quot;:{<br>         &quot;decision&quot;:{<br>            &quot;type&quot;:&quot;string&quot;,<br>            &quot;enum&quot;:[<br>               &quot;True&quot;,<br>               &quot;False&quot;<br>            ],<br>            &quot;description&quot;:&quot;True if the input meets this condition &#39;Does submission meet the ALL these requirements (uses typescript, uses tailwindcss, functional demo)&#39;, False otherwise.&quot;<br>         }<br>      },<br>      &quot;required&quot;:[<br>         &quot;decision&quot;<br>      ]<br>   }<br>}</pre><p>If you’re curious why I love functions so much or what I’ve built with them you should check out <a href=\"https://www.agenthub.dev/\">AgentHub</a>!</p><p><strong>AgentHub is the </strong><a href=\"https://www.ycombinator.com/launches/JcG-agenthub-automate-any-workflow-with-ai\"><strong>Y Combinator-backed startup</strong></a><strong> I co-founded that let’s you automate any repetitive or complex workflow with AI via a simple drag and drop no-code platform.</strong></p><blockquote>“Imagine Zapier but AI-first and on crack.” — Me</blockquote><p>Automations are built with individual nodes called “Operators” that are linked together to create power AI pipelines. We have a catalogue of AI powered operators that leverage functions under the hood.</p><figure><img alt=\"\" src=\"https://cdn-images-1.medium.com/max/1024/1*U3Cqe59WNC6mFQn3-3O26A.png\" /><figcaption>Our current AI-powered operators that use functions!</figcaption></figure><p>Check out these templates to see examples of function use-cases on AgentHub: <a href=\"https://www.agenthub.dev/templates/sales_crm/sales_leads_scoring_model\">Scoring</a>, <a href=\"https://www.agenthub.dev/templates/media_news/news_story_categorizer\">Categorization</a>, <a href=\"https://www.agenthub.dev/templates/media_news/autonomous_twitter_bot\">Option-Selection</a>,</p><p>If you want to start building <a href=\"https://www.agenthub.dev/\">AgentHub</a> is live and ready to use! We’re very active in our <a href=\"https://discord.gg/SyCVmrzhCc\">discord community</a> and are happy to help you build your automations if needed.</p><p>Feel free to follow the <a href=\"https://twitter.com/AgentHub_AI\">official AgentHub twitter</a> for updates and <a href=\"https://twitter.com/MaxBrodeurUrbas\">myself for AI-related content.</a></p><img src=\"https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=ccbd1d3f9fd7\" width=\"1\" height=\"1\" alt=\"\"><hr><p><a href=\"https://medium.com/better-programming/gpt-function-calling-5-underrated-use-cases-ccbd1d3f9fd7\">GPT Function Calling: 5 Underrated Use Cases</a> was originally published in <a href=\"https://betterprogramming.pub\">Better Programming</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>"},{"guid":"https://medium.com/p/8d81fccd8250","link":"https://medium.com/better-programming/webassembly-with-go-taking-web-apps-to-the-next-level-8d81fccd8250?source=rss----d0b105d10f0a---4","title":"WebAssembly with Go: Taking Web Apps to the Next Level","author":"Ege Aytin","excerpt":"You might’ve noticed the increasing chatter around WebAssembly (WASM) in the dev community. Its potential is vast, and we’ve found it invaluable in enhancing our open source project! Hi everyone, I’m part of the team behind Permify , an open-source infra that helps developers to create and manage gr","updated":"2023-11-21T12:18:43.843Z","published":"Fri, 10 Nov 2023 17:31:06 GMT","categories":["javascript","golang","tutorial"],"content_html":"<figure><img alt=\"\" src=\"https://cdn-images-1.medium.com/max/1000/1*b4sFFT3X6e0dVCvKAAtMIg.png\" /></figure><p>You might’ve noticed the increasing chatter around <a href=\"https://webassembly.org/\">WebAssembly (WASM)</a> in the dev community. Its potential is vast, and we’ve found it invaluable in enhancing our open source project!</p><p>Hi everyone, I’m part of the team behind <a href=\"https://github.com/Permify/permify\">Permify</a>, an open-source infra that helps developers to create and manage granular permissions throughout their applications.</p><p>In this article, I’ll demonstrate why and how we integrated WebAssembly (WASM) into our <a href=\"https://play.permify.co/\">Playground</a> and gained benefits from its collaboration with Golang.</p><p>What does this playground do? Well, without diving too deep, its a interactive module of Permify which used for creating and testing authorization models.</p><p>Throughout this post, I’ll be sharing:</p><ul><li><strong><em>A brief explanation of WASM and the benefits of using it with Go.</em></strong></li><li><strong><em>A peek into what spurred our choice to integrate WASM in Permify.</em></strong></li><li><strong><em>WASM Implementation, including</em></strong></li><li><strong><em>Quick Warm Up: WASM Implementation with Go</em></strong></li><li><strong><em>Deeper Dive: Permify’s WASM Code Breakdown</em></strong></li><li><strong><em>Frontend: Steps to Embed Go WASM in a React Application</em></strong></li></ul><p>By the end, you should have a clearer understanding of why and how we leveraged WASM’s capabilities for our project.</p><h3>Understanding WebAssembly</h3><p>WebAssembly (Wasm) has established itself as a pivotal technology, enabling quick and efficient code execution in web browsers and forming a robust bridge between web applications and the high-performance typically associated with native applications.</p><h3>1. Unveiling WebAssembly:</h3><p>Wasm acts as a low-level virtual machine, executing a compact binary code that’s translated from high-level languages.</p><p>Primary Advantages:</p><ul><li>Universal Browser Support: Thanks to its support from all major browsers, Wasm delivers consistent performance across diverse platforms.</li><li>Near-Native Performance: Intentionally designed to execute binary code at a speed akin to native applications, Wasm enhances the responsiveness of web applications considerably.</li></ul><p>In our open-source project, Permify, we strategically incorporated Go (also known as Golang) into its foundational core, selecting it for its widely recognized static typing, concurrency handling, and performance optimization. When the development journey led us to craft the Permify Playground, WebAssembly stepped into the spotlight as a crucial element.</p><h3>2. Blending Go &amp; WebAssembly:</h3><ul><li>Characteristics of Go: Celebrated for its optimal performance and concurrency handling capabilities, Go has carved a sturdy standing within the developer community.</li><li>Synergy with WebAssembly: The translation of Go code into WebAssembly enables developers to effectively utilize Go’s robust performance and concurrency management directly within the browser, propelling the creation of powerful, efficient, and scalable web applications.</li></ul><p>Our journey isn’t just about melding Go and WebAssembly. Moving forward, we’ll unearth why Wasm was pinpointed as the technology of choice for the Permify Playground development and what significant benefits were reaped from this decision.</p><h3>Why WebAssembly?</h3><p>The inception of the Permify Playground brought with it a key question: How to showcase our capabilities without being entwined in the complexities and maintenance woes of traditional server architectures? WebAssembly appeared as a shining answer. Adopting this binary instruction format allowed us to:</p><ul><li>Execute In-Browser: Permify’s playground could operate straight within the browser, sidestepping server maintenance overheads and repetitive API calls, and notably, making ongoing maintenance a breeze in comparison to older server-based approaches.</li><li>Achieve Peak Performance: Employing WebAssembly ensures that our Go application operates with a level of performance that competes with native applications, enhancing user interactions and bolstering response times.</li></ul><h3>Harvesting Technical Benefits and Gathering User Feedback</h3><p>Utilizing WebAssembly in our Permify Playground led us down a path of discernible technical advantages and an embrace from the community:</p><ul><li>Swift Execution: By side-stepping server interactions and deploying WebAssembly in-browser, we’ve been able to deliver ultra-fast response times.</li><li>Uncomplicated User Interface: Centralizing our playground in the browser, we’ve dispelled complexities associated with multi-tool workflows, delivering a clean and straightforward user experience.</li><li>Community Validation: The affirming feedback and positive reception from the developer community stand as validation of our technological choices and implementations.</li></ul><p>Join us in the following sections as we delve deeper into the technicalities, feedback, and learnings from our adventure, providing a thorough exploration of our endeavours with WebAssembly.</p><h3>WASM Implementation with Go</h3><p>Before we explore Permify’s use of WebAssembly (WASM) and Go, let’s understand their combination in a sample app. What follows is a step-by-step guide to bringing them together, setting the stage for our deeper dive into Permify’s implementation.</p><h3>1. Transforming Go into WebAssembly:</h3><ul><li><strong>Steps:</strong></li></ul><ol><li>To get started, ensure you’ve set the WebAssembly build target in Go:</li></ol><pre>GOOS=js GOARCH=wasm go build -o main.wasm main.go</pre><ol><li>Next, apply optimizations to reduce the file size and enhance performance:</li></ol><pre>wasm-opt main.wasm --enable-bulk-memory -Oz -o play.wasm</pre><ul><li><strong>Handling Events:</strong></li></ul><p>Suppose you want your Go function to react to a button click from your web page:</p><pre>package main<br><br>import &quot;syscall/js&quot;<br><br>func registerCallbacks() {<br>    js.Global().Set(&quot;handleClick&quot;, js.FuncOf(handleClick))<br>}<br><br>func handleClick(this js.Value, inputs []js.Value) interface{} {<br>    println(&quot;Button clicked!&quot;)<br>    return nil<br>}</pre><p>In your HTML, after loading your WebAssembly module:</p><pre>&lt;button onclick=&quot;window.handleClick()&quot;&gt;Click me&lt;/button&gt;</pre><h3>2. Integrating with Web Pages:</h3><ul><li><strong>Initializing Wasm:</strong></li></ul><p>Ensure you have the wasm_exec.js script linked, then instantiate your Wasm module:</p><pre>&lt;script src=&quot;wasm_exec.js&quot;&gt;&lt;/script&gt;<br>&lt;script&gt;<br>    const go = new Go();<br>    WebAssembly.instantiateStreaming(fetch(&quot;play.wasm&quot;), go.importObject).then((result) =&gt; {<br>        go.run(result.instance);<br>    });<br>&lt;/script&gt;</pre><ul><li><strong>Interacting with the DOM:</strong></li></ul><p>Accessing and modifying web elements is fundamental. For instance, changing the content of a paragraph element from Go would look something like this:</p><pre>func updateDOMContent() {<br>    document := js.Global().Get(&quot;document&quot;)<br>    element := document.Call(&quot;getElementById&quot;, &quot;myParagraph&quot;)<br>    element.Set(&quot;innerText&quot;, &quot;Updated content from Go!&quot;)<br>}</pre><h3>3. The Gains: Efficiency &amp; Speed:</h3><ul><li><strong>Go’s Goroutines in the Browser:</strong></li></ul><p>Imagine having multiple data fetch operations that can run simultaneously without blocking the main thread:</p><pre>func fetchData(url string, ch chan string) {<br>    // Simulate data fetch.<br>    ch &lt;- &quot;Data from &quot; + url<br>}<br><br>func main() {<br>    ch := make(chan string)<br>    go fetchData(&quot;&lt;https://api.example1.com&gt;&quot;, ch)<br>    go fetchData(&quot;&lt;https://api.example2.com&gt;&quot;, ch)<br><br>    data1 := &lt;-ch<br>    data2 := &lt;-ch<br>    println(data1, data2)<br>}</pre><p>Navigating through Go and WebAssembly (WASM) showcases a powerful union, merging Go’s concurrent processing with WASM’s rapid client-side execution. The depth explored in our sample app lights the way forward into Permify, where we apply these technological strengths into a scalable, real-world authorization system.</p><h3>Deeper Dive: Permify’s WASM Code Breakdown</h3><p>Let’s dive a bit deeper into the heart of our WebAssembly integration by exploring the key segments of our Go-based WASM code.</p><h3>1. Setting up the Go-to-WASM Environment</h3><p>involves preparing and specifying our Go code to be compiled for a WebAssembly runtime.</p><pre>// go:build wasm<br>// +build wasm</pre><p>These lines serve as directives to the Go compiler, signaling that the following code is designated for a WebAssembly runtime environment. Specifically:</p><ul><li>//go:build wasm: A build constraint ensuring the code is compiled only for WASM targets, adhering to modern syntax.</li><li>// +build wasm: An analogous constraint, utilizing older syntax for compatibility with prior Go versions.</li></ul><p>In essence, these directives guide the compiler to include this code segment only when compiling for a WebAssembly architecture, ensuring an appropriate setup and function within this specific runtime.</p><h3>2. Bridging JavaScript and Go with the run Function</h3><pre>package main<br><br>import (<br> &quot;context&quot;<br> &quot;encoding/json&quot;<br> &quot;syscall/js&quot;<br><br> &quot;google.golang.org/protobuf/encoding/protojson&quot;<br><br> &quot;github.com/Permify/permify/pkg/development&quot;<br>)<br><br>var dev *development.Development<br><br>func run() js.Func {<br>  // The `run` function returns a new JavaScript function<br>  // that wraps the Go function.<br> return js.FuncOf(func(this js.Value, args []js.Value) interface{} {<br><br>  // t will be used to store the unmarshaled JSON data.<br>  // The use of an empty interface{} type means it can hold any type of value.<br>  var t interface{}<br><br>  // Unmarshal JSON from JavaScript function argument (args[0]) to Go&#39;s data structure (map).<br>  // args[0].String() gets the JSON string from the JavaScript argument,<br>  // which is then converted to bytes and unmarshaled (parsed) into the map `t`.<br>  err := json.Unmarshal([]byte(args[0].String()), &amp;t)<br><br>  // If an error occurs during unmarshaling (parsing) the JSON,<br>  // it returns an array with the error message &quot;invalid JSON&quot; to JavaScript.<br>  if err != nil {<br>   return js.ValueOf([]interface{}{&quot;invalid JSON&quot;})<br>  }<br><br>  // Attempt to assert that the parsed JSON (`t`) is a map with string keys.<br>  // This step ensures that the unmarshaled JSON is of the expected type (map).<br>  input, ok := t.(map[string]interface{})<br><br>  // If the assertion is false (`ok` is false),<br>  // it returns an array with the error message &quot;invalid JSON&quot; to JavaScript.<br>  if !ok {<br>   return js.ValueOf([]interface{}{&quot;invalid JSON&quot;})<br>  }<br><br>  // Run the main logic of the application with the parsed input.<br>  // It’s assumed that `dev.Run` processes `input` in some way and returns any errors encountered during that process.<br>  errors := dev.Run(context.Background(), input)<br><br>  // If no errors are present (the length of the `errors` slice is 0),<br>  // return an empty array to JavaScript to indicate success with no errors.<br>  if len(errors) == 0 {<br>   return js.ValueOf([]interface{}{})<br>  }<br><br>  // If there are errors, each error in the `errors` slice is marshaled (converted) to a JSON string.<br>  // `vs` is a slice that will store each of these JSON error strings.<br>  vs := make([]interface{}, 0, len(errors))<br><br>  // Iterate through each error in the `errors` slice.<br>  for _, r := range errors {<br>   // Convert the error `r` to a JSON string and store it in `result`.<br>   // If an error occurs during this marshaling, it returns an array with that error message to JavaScript.<br>   result, err := json.Marshal(r)<br>   if err != nil {<br>    return js.ValueOf([]interface{}{err.Error()})<br>   }<br>   // Add the JSON error string to the `vs` slice.<br>   vs = append(vs, string(result))<br>  }<br><br>  // Return the `vs` slice (containing all JSON error strings) to JavaScript.<br>  return js.ValueOf(vs)<br> })<br>}</pre><p>Within the realm of Permify, the run function stands as a cornerstone, executing a crucial bridging operation between JavaScript inputs and Go&#39;s processing capabilities. It orchestrates real-time data interchange in JSON format, safeguarding that Permify&#39;s core functionalities are smoothly and instantaneously accessible via a browser interface.</p><p>Digging into run:</p><ul><li>JSON Data Interchange: Translating JavaScript inputs into a format utilizable by Go, the function unmarshals JSON, transferring data between JS and Go, assuring that the robust processing capabilities of Go can seamlessly manipulate browser-sourced inputs.</li><li>Error Handling: Ensuring clarity and user-awareness, it conducts meticulous error-checking during data parsing and processing, returning relevant error messages back to the JavaScript environment to ensure user-friendly interactions.</li><li>Contextual Processing: By employing dev.Run, it processes the parsed input within a certain context, managing application logic while handling potential errors to assure steady data management and user feedback.</li><li>Bidirectional Communication: As errors are marshaled back into JSON format and returned to JavaScript, the function ensures a two-way data flow, keeping both environments in synchronized harmony.</li></ul><p>Thus, through adeptly managing data, error-handling, and ensuring a fluid two-way communication channel, run serves as an integral bridge, linking JavaScript and Go to ensure the smooth, real-time operation of Permify within a browser interface. This facilitation of interaction not only heightens user experience but also leverages the respective strengths of JavaScript and Go within the Permify environment.</p><h3>3. Main Execution and Initialization</h3><pre>// Continuing from the previously discussed code...<br><br>func main() {<br>  // Instantiate a channel, &#39;ch&#39;, with no buffer, acting as a synchronization point for the goroutine.<br>  ch := make(chan struct{}, 0)<br><br>  // Create a new instance of &#39;Container&#39; from the &#39;development&#39; package and assign it to the global variable &#39;dev&#39;.<br>  dev = development.NewContainer()<br><br>  // Attach the previously defined &#39;run&#39; function to the global JavaScript object,<br>  // making it callable from the JavaScript environment.<br>  js.Global().Set(&quot;run&quot;, run())<br><br>  // Utilize a channel receive expression to halt the &#39;main&#39; goroutine, preventing the program from terminating.<br>  &lt;-ch<br>}</pre><ol><li>ch := make(chan struct{}, 0): A synchronization channel is created to coordinate the activity of goroutines (concurrent threads in Go).</li><li>dev = development.NewContainer(): Initializes a new container instance from the development package and assigns it to dev.</li><li>js.Global().Set(&quot;run&quot;, run()): Exposes the Go run function to the global JavaScript context, enabling JavaScript to call Go functions.</li><li>&lt;-ch: Halts the main goroutine indefinitely, ensuring that the Go WebAssembly module remains active in the JavaScript environment.</li></ol><p>In summary, the code establishes a Go environment running within WebAssembly that exposes specific functionality (run function) to the JavaScript side and keeps itself active and available for function calls from JavaScript.</p><h3>Building the Go Code into a WASM Module</h3><p>Before we delve into Permify’s rich functionalities, it’s paramount to elucidate the steps of converting our Go code into a WASM module, priming it for browser execution.</p><p>For enthusiasts eager to delve deep into the complete Go codebase, don’t hesitate to browse our GitHub repository: <a href=\"https://github.com/Permify/permify/tree/master/pkg/development\">Permify Wasm Code</a>.</p><h3>1. Compiling to WASM</h3><p>Kickstart the transformation of our Go application into a WASM binary with this command:</p><pre>GOOS=js GOARCH=wasm go build -o permify.wasm main.go</pre><p>This directive cues the Go compiler to churn out a .wasm binary attuned for JavaScript environments, with main.go as the source. The output, permify.wasm, is a concise rendition of our Go capabilities, primed for web deployment.</p><h3>2. WASM Exec JS</h3><p>In conjunction with the WASM binary, the Go ecosystem offers an indispensable JavaScript piece named wasm_exec.js. It&#39;s pivotal for initializing and facilitating our WASM module within a browser setting. You can typically locate this essential script inside the Go installation, under misc/wasm.</p><p>However, to streamline your journey, we’ve hosted wasm_exec.js right here for direct access: <a href=\"https://github.com/Permify/permify/tree/master/playground/src/loadWasm\">wasm_exec</a>.</p><pre>cp &quot;$(go env GOROOT)/misc/wasm/wasm_exec.js&quot; .</pre><p>Equipped with these pivotal assets — the WASM binary and its companion JavaScript — the stage is set for its amalgamation into our frontend.</p><h3>Steps to Embed Go WASM in a React Application</h3><h3>1. Setting Up the React Application Structure</h3><p>To kick things off, ensure you have a directory structure that clearly separates your WebAssembly-related code from the rest of your application. Based on your given structure, the loadWasm folder seems to be where all the magic happens:</p><pre>loadWasm/<br>│<br>├── index.tsx            // Your main React component that integrates WASM.<br>├── wasm_exec.js         // Provided by Go, bridges the gap between Go&#39;s WASM and JS.<br>└── wasmTypes.d.ts       // TypeScript type declarations for WebAssembly.</pre><p>To view the complete structure and delve into the specifics of each file, refer to the <a href=\"https://github.com/Permify/permify/tree/master/playground/src/loadWasm\">Permify Playground on GitHub</a>.</p><h3>2. Establishing Type Declarations</h3><p>Inside the wasmTypes.d.ts, global type declarations are made which expand upon the Window interface to acknowledge the new methods brought in by Go&#39;s WebAssembly:</p><pre>declare global {<br>  export interface Window {<br>    Go: any;<br>    run: (shape: string) =&gt; any[];<br>  }<br>}<br>export {};</pre><p>This ensures TypeScript recognizes the Go constructor and the run method when called on the global window object.</p><h3>3. Preparing the WebAssembly Loader</h3><p>In index.tsx, several critical tasks are accomplished:</p><ul><li><strong>Import Dependencies:</strong> First off, we import the required JS and TypeScript declarations:</li></ul><pre>import &quot;./wasm_exec.js&quot;;<br>import &quot;./wasmTypes.d.ts&quot;;</pre><ul><li><strong>WebAssembly Initialization:</strong> The asynchronous function loadWasm takes care of the entire process:</li></ul><pre>async function loadWasm(): Promise&lt;void&gt; {<br>  const goWasm = new window.Go();<br>  const result = await WebAssembly.instantiateStreaming(<br>    fetch(&quot;play.wasm&quot;),<br>    goWasm.importObject<br>  );<br>  goWasm.run(result.instance);<br>}</pre><p>Here, new window.Go() initializes the Go WASM environment. WebAssembly.instantiateStreaming fetches the WASM module, compiles it, and creates an instance. Finally, goWasm.run activates the WASM module.</p><ul><li><strong>React Component with Loader UI:</strong> The LoadWasm component uses the useEffect hook to asynchronously load the WebAssembly when the component mounts:</li></ul><pre>export const LoadWasm: React.FC&lt;React.PropsWithChildren&lt;{}&gt;&gt; = (props) =&gt; {<br>  const [isLoading, setIsLoading] = React.useState(true);<br><br>  useEffect(() =&gt; {<br>    loadWasm().then(() =&gt; {<br>      setIsLoading(false);<br>    });<br>  }, []);<br><br>  if (isLoading) {<br>    return (<br>      &lt;div className=&quot;wasm-loader-background h-screen&quot;&gt;<br>        &lt;div className=&quot;center-of-screen&quot;&gt;<br>          &lt;SVG src={toAbsoluteUrl(&quot;/media/svg/rocket.svg&quot;)} /&gt;<br>        &lt;/div&gt;<br>      &lt;/div&gt;<br>    );<br>  } else {<br>    return &lt;React.Fragment&gt;{props.children}&lt;/React.Fragment&gt;;<br>  }<br>};</pre><p>While loading, SVG rocket is displayed to indicate that initialization is ongoing. This feedback is crucial as users might otherwise be uncertain about what’s transpiring behind the scenes. Once loading completes, children components or content will render.</p><h3>4. Calling WebAssembly Functions</h3><p>Given your Go WASM exposes a method named run, you can invoke it as follows:</p><pre>function Run(shape) {<br>  return new Promise((resolve) =&gt; {<br>    let res = window.run(shape);<br>    resolve(res);<br>  });<br>}</pre><p>This function essentially acts as a bridge, allowing the React frontend to communicate with the Go backend logic encapsulated in the WASM.</p><h3>5. Implementing the Run Button in React</h3><p>To integrate a button that triggers the WebAssembly function when clicked, follow these steps:</p><ol><li><strong>Creating the Button Component</strong></li></ol><p>First, we’ll create a simple React component with a button:</p><pre>import React from &quot;react&quot;;<br><br>type RunButtonProps = {<br>  shape: string;<br>  onResult: (result: any[]) =&gt; void;<br>};<br><br>function RunButton({ shape, onResult }: RunButtonProps) {<br>  const handleClick = async () =&gt; {<br>    let result = await Run(shape);<br>    onResult(result);<br>  };<br><br>  return &lt;button onClick={handleClick}&gt;Run WebAssembly&lt;/button&gt;;<br>}</pre><p>In the code above, the RunButton component accepts two props:</p><ul><li>shape: The shape argument to pass to the WebAssembly run function.</li><li>onResult: A callback function that receives the result of the WebAssembly function and can be used to update the state or display the result in the UI.</li></ul><ol><li>Integrating the Button in the Main Component</li></ol><p>Now, in your main component (or wherever you’d like to place the button), integrate the RunButton:</p><pre>import React, { useState } from &quot;react&quot;;<br>import RunButton from &quot;./path_to_RunButton_component&quot;; // Replace with the actual path<br><br>function App() {<br>  const [result, setResult] = useState&lt;any[]&gt;([]);<br><br>  // Define the shape content<br>  const shapeContent = {<br>    schema: `|-<br>    entity user {}<br><br>    entity account {<br>        relation owner @user<br>        relation following @user<br>        relation follower @user<br><br>        attribute public boolean<br>        action view = (owner or follower) or public  <br>    }<br><br>    entity post {<br>        relation account @account<br><br>        attribute restricted boolean<br><br>        action view = account.view<br><br>        action comment = account.following not restricted<br>        action like = account.following not restricted<br>    }`,<br>    relationships: [<br>      &quot;account:1#owner@user:kevin&quot;,<br>      &quot;account:2#owner@user:george&quot;,<br>      &quot;account:1#following@user:george&quot;,<br>      &quot;account:2#follower@user:kevin&quot;,<br>      &quot;post:1#account@account:1&quot;,<br>      &quot;post:2#account@account:2&quot;,<br>    ],<br>    attributes: [<br>      &quot;account:1$public|boolean:true&quot;,<br>      &quot;account:2$public|boolean:false&quot;,<br>      &quot;post:1$restricted|boolean:false&quot;,<br>      &quot;post:2$restricted|boolean:true&quot;,<br>    ],<br>    scenarios: [<br>      {<br>        name: &quot;Account Viewing Permissions&quot;,<br>        description:<br>          &quot;Evaluate account viewing permissions for &#39;kevin&#39; and &#39;george&#39;.&quot;,<br>        checks: [<br>          {<br>            entity: &quot;account:1&quot;,<br>            subject: &quot;user:kevin&quot;,<br>            assertions: {<br>              view: true,<br>            },<br>          },<br>        ],<br>      },<br>    ],<br>  };<br><br>  return (<br>    &lt;div&gt;<br>      &lt;RunButton shape={JSON.stringify(shapeContent)} onResult={setResult} /&gt;<br>      &lt;div&gt;<br>        Results:<br>        &lt;ul&gt;<br>          {result.map((item, index) =&gt; (<br>            &lt;li key={index}&gt;{item}&lt;/li&gt;<br>          ))}<br>        &lt;/ul&gt;<br>      &lt;/div&gt;<br>    &lt;/div&gt;<br>  );<br>}</pre><p>In this example, App is a component that contains the RunButton. When the button is clicked, the result from the WebAssembly function is displayed in a list below the button.</p><h3>Conclusion</h3><p>Throughout this exploration, the integration of WebAssembly with Go was unfolded, illuminating the pathway toward enhanced web development and optimal user interactions within browsers.</p><p>The journey involved setting up the Go environment, converting Go code to WebAssembly, and executing it within a web context, ultimately giving life to the interactive platform showcased at <a href=\"https://play.permify.co/\">play.permify.co</a>.</p><p>This platform stands not only as an example but also as a beacon, illustrating the concrete and potent capabilities achievable when intertwining these technological domains.</p><img src=\"https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=8d81fccd8250\" width=\"1\" height=\"1\" alt=\"\"><hr><p><a href=\"https://medium.com/better-programming/webassembly-with-go-taking-web-apps-to-the-next-level-8d81fccd8250\">WebAssembly with Go: Taking Web Apps to the Next Level</a> was originally published in <a href=\"https://betterprogramming.pub\">Better Programming</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>"},{"guid":"https://medium.com/p/3ee5d41f81a4","link":"https://medium.com/better-programming/3-fundamental-concepts-to-fully-understand-how-the-fetch-api-works-3ee5d41f81a4?source=rss----d0b105d10f0a---4","title":"3 Fundamental Concepts to Fully Understand how the Fetch API Works","author":"Jay Cruz","updated":"2023-11-10T17:30:24.902Z","published":"Fri, 10 Nov 2023 17:30:24 GMT","categories":["fetch-api","software-development","javascript","web-development","programming"]},{"guid":"https://medium.com/p/48809a853fae","link":"https://medium.com/better-programming/deploy-coreml-models-on-the-server-with-vapor-48809a853fae?source=rss----d0b105d10f0a---4","title":"Deploy CoreML Models on the Server with Vapor","author":"Drew Althage","excerpt":"Get the benefits of Apple’s ML tools server-side. SwiftUI client showing image classification results Recently, at Sovrn , we had an AI Hackathon where we were encouraged to experiment with anything related to machine learning. The Hackathon yielded some fantastic projects from across the company. E","updated":"2023-11-10T17:30:15.819Z","published":"Fri, 10 Nov 2023 17:30:15 GMT","categories":["swift","programming","ios","machine-learning","apple"],"content_html":"<p>Get the benefits of Apple’s ML tools server-side.</p><figure><img alt=\"\" src=\"https://cdn-images-1.medium.com/max/1024/1*XMjKfWYZYPikQ0pJ391YaA.png\" /><figcaption>SwiftUI client showing image classification results</figcaption></figure><p>Recently, at <a href=\"https://www.sovrn.com/\">Sovrn</a>, we had an AI Hackathon where we were encouraged to experiment with anything related to machine learning. The Hackathon yielded some fantastic projects from across the company. Everything from SQL query generators to chatbots that can answer questions about our products and other incredible work. I thought this would be a great opportunity to learn more about Apple’s ML tools and maybe even build something with real business value.</p><p>A few of my colleagues and I teamed up to play with CreateML and CoreML to see if we could integrate some ML functionality into our iOS app. We got a model trained and integrated into our app in several hours, which was pretty amazing. But we quickly realized that we had a few problems to solve before we could actually ship this thing.</p><ul><li>The model was hefty. It was about 50MB. That’s a lot of space to take up in our app bundle.</li><li>We wanted to update the model without releasing a new app version.</li><li>We wanted to use the model in the web browser as well.</li></ul><p>We didn’t have time to solve all of these problems. But the other day I was exploring the <a href=\"https://vapor.codes/\">Vapor</a> web framework and the thought hit me, “Why not deploy CoreML models on the server?”</p><p>Apple provides a few pre-trained models, so today we’ll deploy an image classification model on the server behind a REST API with Vapor and create a SwiftUI client to consume it.</p><h3>Foreword</h3><p>This prototype is just that, a prototype. It’s not meant to be a production-ready solution. It’s meant to be a proof of concept. There will be warnings in the console, and the code won’t be very clean, but it will work and hopefully get your wheels turning.</p><p>If you want to skip all this, or if you do want to follow along, you can find the source code for this project on <a href=\"https://github.com/drewalth/coreml-web-api\">GitHub</a>.</p><p>Okay, disclaimers over. Let’s get started!</p><h3>Requirements</h3><ul><li>Xcode 15</li><li>macOS 14</li><li>Homebrew</li><li>Apple Developer Account + Physical Device for testing</li></ul><h3>Getting Started</h3><p>First start by creating a new directory that will house our Xcode workspace. We’ll call it coreml-web-api .</p><pre>cd ~/Desktop &amp;&amp; mkdir coreml-web-api &amp;&amp; cd coreml-web-api</pre><p>Now let&#39;s install Vapor and bootstrap a brand new server. See <a href=\"https://docs.vapor.codes/\">the docs</a> for more details.</p><pre>brew install vapor<br>vapor new server -n<br>open Package.swift</pre><p>We want our users to be able to upload images for classification so add a new route called classify that supports this. In server/Sources/App/routes.swift , clear out all that generated boilerplate, and add in the following:</p><pre>import CoreImage<br>import Vapor<br><br>func routes(_ app: Application) throws {<br>    app.post(&quot;classify&quot;) { req -&gt; [ClassifierResult] in<br>        let classificationReq = try req.content.decode(ClassificationRequest.self)<br>        let imageBuffer = classificationReq.file.data<br>        guard let fileData = imageBuffer.getData(at: imageBuffer.readerIndex, length: imageBuffer.readableBytes),<br>              let ciImage = CIImage(data: fileData)<br>        else {<br>            throw Errors.badImageData<br>        }<br><br>        let classifier = Classifier() // we&#39;ll add this in a sec<br><br>        return try classifier.classify(image: ciImage)<br>    }<br>}<br><br>enum Errors: Error {<br>    case badImageData // or whatever<br>}<br><br>struct ClassificationRequest: Content {<br>    var file: File<br>}</pre><p>Also, bump up the max file size allowed for uploads in configure.swift :</p><pre>import Vapor<br><br>// configures your application<br>public func configure(_ app: Application) async throws {<br>    app.routes.defaultMaxBodySize = &quot;10mb&quot;<br><br>    // register routes<br>    try routes(app)<br>}</pre><p>Alright, now let&#39;s write up a Classifier API. First, head over to <a href=\"https://developer.apple.com/machine-learning/models/\">Apple’s ML page</a> to download a pre-trained model of your choosing. In this demo, I’m using the Resnet50 model. We’ll add this to the package in just a moment.</p><p>Add a new file called Classifier and drop in the following:</p><pre>import CoreImage<br>import Vapor<br>import Vision<br><br>struct Classifier {<br>    func classify(image: CIImage) throws -&gt; [ClassifierResult] {<br>        let url = Bundle.module.url(forResource: &quot;Resnet50&quot;, withExtension: &quot;mlmodelc&quot;)!<br>        guard let model = try? VNCoreMLModel(for: Resnet50(contentsOf: url, configuration: MLModelConfiguration()).model) else {<br>            throw Errors.unableToLoadMLModel<br>        }<br><br>        let request = VNCoreMLRequest(model: model)<br><br>        let handler = VNImageRequestHandler(ciImage: image)<br><br>        try? handler.perform([request])<br><br>        guard let results = request.results as? [VNClassificationObservation] else {<br>            throw Errors.noResults<br>        }<br><br>        return results.map { ClassifierResult(label: $0.identifier, confidence: $0.confidence) }<br>    }<br><br>    enum Errors: Error {<br>        case unableToLoadMLModel<br>        case noResults<br>    }<br>}<br><br>struct ClassifierResult: Encodable, Content {<br>    var label: String<br>    var confidence: Float<br>}</pre><p>Let’s break this down.</p><p>First, we load the model. Adding a CoreML model to a package is not super straightforward. We need to compile the .mlmodelourselves and add some files to Sources/. We’ll go over that in a few but this wonkiness explains why loading the model might look slightly different from adding one to a standard Xcode project.</p><p>Once the model is loaded, we prepare the request and the request handler; then we do the classification. To send the results as JSON to the client, we need to remap the results to a structure that conforms to Encodable and Content .</p><h4>Adding the Model to the Package</h4><p>This part definitely took me the longest to figure out. Unfortunately, this step is pretty manual; we can’t just drag and drop the model into the project. So, at the root of the server package, add a new folder called MLModelSource and add the Resnet50.mlmodel file here. Create another folder called Resourcesat server/Sources/App/Resources/ .</p><p>Now, we need to compile the model, add the Swift class to sources, and include the .mlmodelc in the package bundle. The compilation steps are repetitive so we’ll place them in a Makefile target. In the project root, create a Makefile:</p><pre># ~/Desktop/coreml-web-api/<br>touch Makefile</pre><p>And add a compile_ml_modeltarget:</p><pre>compile_ml_model:<br>   cd server/MLModelSource &amp;&amp; \\<br>   xcrun coremlcompiler compile Resnet50.mlmodel ../Sources/App/Resources &amp;&amp; \\<br>   xcrun coremlcompiler generate Resnet50.mlmodel ../Sources/App/Resources --language Swift</pre><p>Next, add this to the executable target inPackage.swift file:</p><pre>resources: [<br>    .copy(&quot;Resources/Resnet50.mlmodelc&quot;),<br>]</pre><p>The target should look like this:</p><pre>.executableTarget(<br>    name: &quot;App&quot;,<br>    dependencies: [<br>        .product(name: &quot;Vapor&quot;, package: &quot;vapor&quot;),<br>    ],<br>    resources: [<br>        .copy(&quot;Resources/Resnet50.mlmodelc&quot;),<br>    ]<br>),</pre><p>Okay, now from the project root, run the compile_ml_model target:</p><pre>make compile_ml_model</pre><p>Awesome!!! Now, we have an amazing server that supports classifying uploaded images using the Resnet50 model. Before we move on to the creating the client, we need to adjust the App scheme to make the server available to a physical device on your network.</p><p>Open up the scheme editor, and add serve --hostname 0.0.0.0 to the run arguments.</p><figure><img alt=\"\" src=\"https://cdn-images-1.medium.com/max/1024/1*9D7VFpFoUNxS6uZPqCVESw.png\" /></figure><p>Sweet. Now, we’ll create a client to do the uploading.</p><h3>iOS Client</h3><p>OK, in Xcode go to File -&gt; New -&gt; Project and add an iOS app to the workspace. We only need SwiftUI, no tests or SwiftData. I’m giving mine a really clever name of CoreMLWebClient … poetic.</p><p>Great. Now, let&#39;s do a little config work. Since we’re going to be using the camera, we need to update the Info.plist with the Privacy — Camera Usage Description key.</p><figure><img alt=\"\" src=\"https://cdn-images-1.medium.com/max/1024/1*PVfyDXPGfo9-oeQIercJjg.png\" /></figure><p>Nice! In our client, we want to give users the option of using the camera or selecting from the photo library. Create a new file called ImagePicker.swift and paste in the following:</p><pre>import SwiftUI<br><br>struct ImagePicker: UIViewControllerRepresentable {<br>    @Binding var sourceType: UIImagePickerController.SourceType<br>    @Environment(\\.presentationMode) private var presentationMode<br>    var completion: (UIImage) -&gt; Void<br><br>    func makeUIViewController(context: Context) -&gt; some UIViewController {<br>        let picker = UIImagePickerController()<br>        picker.sourceType = sourceType<br>        picker.delegate = context.coordinator<br>        return picker<br>    }<br><br>    func updateUIViewController(_: UIViewControllerType, context _: Context) {}<br><br>    func makeCoordinator() -&gt; Coordinator {<br>        Coordinator(self)<br>    }<br><br>    class Coordinator: NSObject, UINavigationControllerDelegate, UIImagePickerControllerDelegate {<br>        var parent: ImagePicker<br><br>        init(_ parent: ImagePicker) {<br>            self.parent = parent<br>        }<br><br>        func imagePickerController(_: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey: Any]) {<br>            if let image = info[.originalImage] as? UIImage {<br>                parent.completion(image)<br>            }<br>            parent.presentationMode.wrappedValue.dismiss()<br>        }<br>    }<br>}</pre><p>We’ll use the sourceType binding to switch between the camera and the library.</p><p>Now, we’ll add a Classifierto handle the image uploading and return the classification results. I’m jumping around a little, but all this will come together in a few. Create a new file called Classifier.swift and add this in:</p><pre>import Foundation<br>import UIKit<br><br>struct Classifier {<br>    /// replace this with your dev machine IP address<br>    /// for testing with a physical device.<br>    private let host = &quot;localhost&quot;<br><br>    func classify(image: UIImage) async throws -&gt; [ClassifierResult] {<br>        // Ensure the URL is valid<br>        guard let uploadURL = URL(string: &quot;http://\\(host):8080/classify&quot;) else {<br>            throw URLError(.badURL)<br>        }<br><br>        // Convert the image to JPEG data<br>        guard let imageData = image.jpegData(compressionQuality: 1.0) else {<br>            throw URLError(.unknown)<br>        }<br><br>        // Generate boundary string using a unique per-app string<br>        let boundary = &quot;Boundary-\\(UUID().uuidString)&quot;<br><br>        // Create a URLRequest object<br>        var request = URLRequest(url: uploadURL)<br>        request.httpMethod = &quot;POST&quot;<br>        request.setValue(&quot;multipart/form-data; boundary=\\(boundary)&quot;, forHTTPHeaderField: &quot;Content-Type&quot;)<br><br>        // Create multipart form body<br>        let body = createMultipartFormData(boundary: boundary, data: imageData, fileName: &quot;photo.jpg&quot;)<br>        request.httpBody = body<br><br>        // Perform the upload task<br>        let (data, response) = try await URLSession.shared.upload(for: request, from: body)<br><br>        // Check the response and throw an error if it&#39;s not a HTTPURLResponse or the status code is not 200<br>        guard let httpResponse = response as? HTTPURLResponse, httpResponse.statusCode == 200 else {<br>            throw URLError(.badServerResponse)<br>        }<br><br>        // Decode the data into an array of ClassifierResult<br>        return try JSONDecoder().decode([ClassifierResult].self, from: data)<br>    }<br><br>    /// Creates a multipart/form-data body with the image data.<br>    /// - Parameters:<br>    ///   - boundary: The boundary string separating parts of the data.<br>    ///   - data: The image data to be included in the request.<br>    ///   - fileName: The filename for the image data in the form-data.<br>    /// - Returns: A `Data` object representing the multipart/form-data body.<br>    private func createMultipartFormData(boundary: String, data: Data, fileName: String) -&gt; Data {<br>        var body = Data()<br><br>        // Add the image data to the raw http request data<br>        body.append(&quot;--\\(boundary)\\r\\n&quot;)<br>        body.append(&quot;Content-Disposition: form-data; name=\\&quot;file\\&quot;; filename=\\&quot;\\(fileName)\\&quot;\\r\\n&quot;)<br>        body.append(&quot;Content-Type: image/jpeg\\r\\n\\r\\n&quot;)<br>        body.append(data)<br>        body.append(&quot;\\r\\n&quot;)<br><br>        // Add the closing boundary<br>        body.append(&quot;--\\(boundary)--\\r\\n&quot;)<br>        return body<br>    }<br><br>    struct ClassifierResult: Decodable, Identifiable {<br>        let id = UUID()<br>        var label: String<br>        var confidence: Float<br>    }<br>}<br><br>// Helper function to append string data to Data object<br>private extension Data {<br>    mutating func append(_ string: String) {<br>        if let data = string.data(using: .utf8) {<br>            append(data)<br>        }<br>    }<br>}</pre><p>Great! Now on to the UI. Back in ContentView , let&#39;s add an enum called RequestStatus to communicate to the user what is going on — this is an easy UX win.</p><pre>enum RequestStatus {<br>    case loading, success, idle, error<br>}</pre><p>Now, we’ll create a view model for ContentView that uses the newly created classifier to upload a photo to the server and share the results with the UI. This is also going to use the new <a href=\"https://developer.apple.com/documentation/observation\">Observation framework</a> ⭐.</p><pre>extension ContentView {<br>    @Observable<br>    class ViewModel {<br>        var requestStatus: RequestStatus = .idle<br>        var results: [Classifier.ClassifierResult] = []<br><br>        private var classifier = Classifier()<br><br>        func upload(_ image: UIImage) {<br>            Task { @MainActor in<br>                do {<br>                    requestStatus = .loading<br>                    results.removeAll()<br>                    results = try await classifier.classify(image: image)<br>                    requestStatus = .success<br>                } catch {<br>                    print(error.localizedDescription)<br>                    requestStatus = .error<br>                }<br>            }<br>        }<br>    }<br>}</pre><p>Now we need to add some state. This stuff should probably go in the view model, but for now, I’m going to add these as member vars to ContentView …</p><pre>// ContentView.swift<br>@State private var selectedImage: UIImage?<br>@State private var isImagePickerPresented = false<br>@State private var viewModel = ViewModel()<br>@State private var sourceType: UIImagePickerController.SourceType = .camera</pre><p>Alright, now we’ll do some more UI building. Replace the body variable with this:</p><pre>    var body: some View {<br>        VStack(spacing: 20) {<br>            HStack(spacing: 20) {<br>                if let image = selectedImage {<br>                    VStack {<br>                        Image(uiImage: image)<br>                            .resizable()<br>                            .scaledToFit()<br>                    }.padding()<br>                        .frame(maxHeight: 350)<br>                }<br>                List {<br>                    ForEach(viewModel.results, id: \\.id) { result in<br>                        VStack(alignment: .leading) {<br>                            Text(result.label)<br>                                .font(.callout)<br>                            Text(formatAsPercentage(result.confidence))<br>                                .font(.caption2)<br>                        }<br>                    }<br>                }<br>            }<br>            Divider()<br>            HStack(spacing: 20) {<br>                actionButton()<br>                if viewModel.requestStatus == .loading {<br>                    ProgressView()<br>                }<br>            }<br>        }<br>        .sheet(isPresented: $isImagePickerPresented) {<br>            ImagePicker(sourceType: $sourceType) { image in<br>                self.selectedImage = image<br>            }<br>        }<br>    }</pre><p>And to address those compiler errors, add two new functions:</p><pre>// ContentView.swift<br>@ViewBuilder<br>private func actionButton() -&gt; some View {<br>    if let image = selectedImage {<br>        Button(&quot;Upload Image&quot;) {<br>            viewModel.upload(image)<br>        }.buttonStyle(.borderedProminent)<br>    } else {<br>        HStack(spacing: 20) {<br>            Button(&quot;Camera&quot;) {<br>                sourceType = .camera<br>                isImagePickerPresented = true<br>            }.buttonStyle(.bordered)<br>            Button(&quot;Photo Library&quot;) {<br>                sourceType = .photoLibrary<br>                isImagePickerPresented = true<br>            }.buttonStyle(.bordered)<br>        }.padding(.bottom, 20)<br>    }<br>}<br><br>// and<br><br>private func formatAsPercentage(_ value: Float) -&gt; String {<br>    String(format: &quot;%.2f%%&quot;, value * 100)<br>}</pre><p>Heck yeah, you guys. If everything has gone according to plan, you should now be able to create/select a picture, upload it to the server, classify the dominant object in the picture, and then display the classification results in the UI!</p><p>If you run into issues, please feel free to reference the source code, or leave a comment below.</p><p>I hope this project inspires you and gets the gears turning for your next ML project.</p><p>Cheers!</p><img src=\"https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=48809a853fae\" width=\"1\" height=\"1\" alt=\"\"><hr><p><a href=\"https://medium.com/better-programming/deploy-coreml-models-on-the-server-with-vapor-48809a853fae\">Deploy CoreML Models on the Server with Vapor</a> was originally published in <a href=\"https://betterprogramming.pub\">Better Programming</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>"},{"guid":"https://medium.com/p/37afb7a6b26c","link":"https://medium.com/better-programming/full-stack-engineers-dont-exist-37afb7a6b26c?source=rss----d0b105d10f0a---4","title":"Full Stack Engineers Don’t Exist!","author":"Stephen Walsh","updated":"2023-11-10T17:28:33.460Z","published":"Fri, 10 Nov 2023 17:28:33 GMT","categories":["software-development","software-engineering","programming","careers","technology"]}]},"meta":{"timestamp":"2026-06-02T16:53:17.711Z","request_id":"48c08a68-e916-431c-88b0-5e8b335edfac"},"status":"ok","message":"Publication posts","success":true}}}},"401":{"description":"Missing or invalid x-oanor-key header"},"402":{"description":"Active subscription required"},"429":{"description":"Rate-limit or monthly quota reached"},"502":{"description":"Upstream did not respond"}}}},"/v1/tag":{"get":{"operationId":"get_v1_tag","tags":["Medium"],"summary":"Tag posts","description":"","parameters":[{"name":"tag","in":"query","required":true,"description":"Topic slug","schema":{"type":"string"},"example":"programming"}],"security":[{"oanorKey":[]}],"responses":{"200":{"description":"OK","content":{"application/json":{"example":{"data":{"feed":{"link":"https://medium.com/tag/programming/latest?source=rss------programming-5","image":"https://cdn-images-1.medium.com/proxy/1*TGH72Nnw24QL3iV9IOm4VA.png","title":"Programming on Medium","description":"Latest stories tagged with Programming on Medium"},"count":9,"items":[{"guid":"https://medium.com/p/36024bdb36c6","link":"https://medium.com/techtofreedom/9-levels-of-profiling-python-apps-in-2026-from-cprofile-to-tachyon-36024bdb36c6?source=rss------programming-5","title":"9 Levels of Profiling Python Apps in 2026: From cProfile to Tachyon","author":"Yang Zhou","updated":"2026-06-02T16:38:28.436Z","published":"Tue, 02 Jun 2026 16:38:28 GMT","categories":["technology","python","software-engineering","programming","coding"]},{"guid":"https://medium.com/p/62467e5d41df","link":"https://medium.com/@kp9810113/the-day-our-2-week-sprint-became-a-6-week-death-march-62467e5d41df?source=rss------programming-5","title":"The Day Our 2-Week Sprint Became a 6-Week Death March","author":"The Concurrent Mind","updated":"2026-06-02T16:37:59.027Z","published":"Tue, 02 Jun 2026 16:37:58 GMT","categories":["programming","technology","software-development","tech","agile"]},{"guid":"https://medium.com/p/df5f5dc124b1","link":"https://medium.com/@folajeff/rhapsody-of-realities-2nd-june-2026-righteousness-is-the-nature-of-god-that-reveals-his-df5f5dc124b1?source=rss------programming-5","title":"RHAPSODY OF REALITIES - 2ND JUNE 2026\n\"Righteousness is the nature of God that reveals His…","author":"STARYLX","updated":"2026-06-02T16:37:56.400Z","published":"Tue, 02 Jun 2026 16:37:56 GMT","categories":["programming","design","productivity","self-improvement","creativity"]},{"guid":"https://medium.com/p/f21e6c82937b","link":"https://ottomancoder.medium.com/flutter-3-44-looks-like-a-minor-update-its-quietly-one-of-the-biggest-in-years-f21e6c82937b?source=rss------programming-5","title":"Flutter 3.44 Looks Like a Minor Update. It’s Quietly One of the Biggest in Years.","author":"Muhammad Usman","updated":"2026-06-02T16:20:29.095Z","published":"Tue, 02 Jun 2026 16:20:29 GMT","categories":["mobile-development","software-development","dart","flutter","programming"]},{"guid":"https://medium.com/p/36df887e70ef","link":"https://blog.cubed.run/i-built-an-ai-assistant-that-turns-messy-human-requests-into-real-tasks-36df887e70ef?source=rss------programming-5","title":"I Built an AI Assistant That Turns Messy Human Requests Into Real Tasks","author":"Ahmad Tariq","updated":"2026-06-02T16:14:41.161Z","published":"Tue, 02 Jun 2026 16:14:41 GMT","categories":["programming","technology","artificial-intelligence","machine-learning","coding"]},{"guid":"https://medium.com/p/581834f48f3c","link":"https://medium.com/javarevisited/9-powerful-java-apis-that-save-development-time-581834f48f3c?source=rss------programming-5","title":"9 Powerful Java APIs That Save Development Time","author":"Gopi C K","updated":"2026-06-02T16:00:16.647Z","published":"Tue, 02 Jun 2026 16:00:16 GMT","categories":["software-development","java","coding","programming"]},{"guid":"https://medium.com/p/c7a719846e47","link":"https://medium.com/javarevisited/i-misused-spring-boot-for-2-years-heres-what-finally-made-it-click-c7a719846e47?source=rss------programming-5","title":"I Misused Spring Boot for 2 Years — Here’s What Finally Made It Click","author":"Pushpak Raut","updated":"2026-06-02T16:00:08.676Z","published":"Tue, 02 Jun 2026 16:00:08 GMT","categories":["java","software-engineering","spring-boot","backend-development","programming"]},{"guid":"https://medium.com/p/3a1d3857692d","link":"https://medium.com/javarevisited/stop-writing-code-youll-regret-dry-kiss-yagni-and-the-law-of-demeter-explained-with-java-3a1d3857692d?source=rss------programming-5","title":"Stop Writing Code You’ll Regret: DRY, KISS, YAGNI, and the Law of Demeter Explained with Java","author":"Sumit Kumar Singh","updated":"2026-06-02T16:00:06.690Z","published":"Tue, 02 Jun 2026 16:00:06 GMT","categories":["system-design-interview","software-development","programming","design","software-engineering"]},{"guid":"https://medium.com/p/1a0385cfbb5a","link":"https://medium.com/javarevisited/command-design-pattern-in-java-a-practical-guide-to-undo-queues-retries-and-clean-architecture-1a0385cfbb5a?source=rss------programming-5","title":"Command Design Pattern in Java: A Practical Guide to Undo, Queues, Retries, and Clean Architecture","author":"Sumit Kumar Singh","updated":"2026-06-02T16:00:04.779Z","published":"Tue, 02 Jun 2026 16:00:04 GMT","categories":["software-engineering","software-development","design","system-design-interview","programming"]}]},"meta":{"timestamp":"2026-06-02T16:53:18.010Z","request_id":"8dfd41c7-b5f1-44aa-b966-7efe6e948129"},"status":"ok","message":"Tag posts","success":true}}}},"401":{"description":"Missing or invalid x-oanor-key header"},"402":{"description":"Active subscription required"},"429":{"description":"Rate-limit or monthly quota reached"},"502":{"description":"Upstream did not respond"}}}},"/v1/user":{"get":{"operationId":"get_v1_user","tags":["Medium"],"summary":"User posts","description":"","parameters":[{"name":"user","in":"query","required":true,"description":"Medium @handle (without @)","schema":{"type":"string"},"example":"medium"}],"security":[{"oanorKey":[]}],"responses":{"200":{"description":"OK","content":{"application/json":{"example":{"data":{"feed":{"link":"https://medium.com/@Medium?source=rss-504c7870fdb6------2","image":"https://cdn-images-1.medium.com/fit/c/150/150/1*8E6Laeaz-zMfU_rkpZUyKw.png","title":"Stories by Medium on Medium","description":"Stories by Medium on Medium"},"count":10,"items":[{"guid":"https://medium.com/p/62edea66ffa4","link":"https://medium.com/blog/updating-our-rules-june-2023-62edea66ffa4?source=rss-504c7870fdb6------2","title":"Updating Our Rules — June 2023","author":"Medium","excerpt":"Updating Our Rules — June 2023 This month, we are updating our Rules . As the world evolves, so do the ways in which people use Medium. To accommodate this, we regularly assess our rules, and adjust them accordingly. We believe that through helping people share their experiences and viewpoints, we c","updated":"2023-06-28T18:01:22.039Z","published":"Wed, 28 Jun 2023 18:01:22 GMT","categories":["rules","medium"],"content_html":"<h3>Updating Our Rules — June 2023</h3><p>This month, we are updating our <a href=\"https://policy.medium.com/medium-rules-30e5502c4eb4\">Rules</a>. As the world evolves, so do the ways in which people use Medium. To accommodate this, we regularly assess our rules, and adjust them accordingly.</p><p>We believe that through helping people share their experiences and viewpoints, we can foster greater levels of understanding, education, and acceptance. We realize that, at various moments in the larger cultural conversation, certain underrepresented groups become targeted, and our rules need to quickly evolve in order to maintain our mission of moving conversation forward. You can read more in our in post “<a href=\"https://blog.medium.com/medium-stands-for-lgbtqia-rights-ee4d63e8052e\">Medium stands for LGBTQIA+ rights</a>.”</p><p>New changes to our rules include expanding and improving the language around how we define hateful conflict to include slurs, deadnaming, and intentional misgendering.</p><p>Additionally, please note that accounts who plagiarize or commit copyright infringement will not be warned, and are not eligible for appeal. Please only post content to Medium which you own or have clear permission to use. If you are unsure if you can use someone else’s content, please see the EFF’s article on <a href=\"https://www.eff.org/issues/bloggers/legal/liability/IP\">“Intellectual Property.”</a></p><p>We also did some general editing clean up, and removed redundant sections to make the rules page cleaner and easier to read.</p><p>The Medium Rules are available <a href=\"https://policy.medium.com/medium-rules-30e5502c4eb4\">here</a>. We <a href=\"https://github.com/Medium/medium-policy/blob/master/Rules.md\">track changes</a> to our rules on Github so you can see how they evolve.</p><p>If you find content or accounts you feel violate our rules, please <a href=\"https://help.medium.com/hc/en-us/articles/217047977-Report-posts-users\">report it.</a> You can use <a href=\"https://help.medium.com/hc/en-us/requests/new\">this form</a> to provide more detail or to report other conduct. Additionally, you can always send an email to <a href=\"mailto:trust@medium.com\">trust@medium.com</a>.</p><img src=\"https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=62edea66ffa4\" width=\"1\" height=\"1\" alt=\"\"><hr><p><a href=\"https://medium.com/blog/updating-our-rules-june-2023-62edea66ffa4\">Updating Our Rules — June 2023</a> was originally published in <a href=\"https://medium.com/blog\">The Medium Blog</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>"},{"guid":"https://medium.com/p/cccf29534bf4","link":"https://policy.medium.com/email-import-terms-of-use-cccf29534bf4?source=rss-504c7870fdb6------2","title":"Email Import Terms of Use","author":"Medium","excerpt":"Effective as of November 8th, 2021 By using this feature to import any email addresses (the “Email Import”), you represent and agree that: You have collected all email addresses that you will import through the Email Import in accordance with all applicable local, state, provincial, national, intern","updated":"2021-11-08T17:24:26.374Z","published":"Mon, 08 Nov 2021 17:24:26 GMT","categories":[],"content_html":"<p>Effective as of November 8th, 2021</p><p>By using this feature to import any email addresses (the “Email Import”), you represent and agree that:</p><ul><li>You have collected all email addresses that you will import through the Email Import in accordance with all applicable local, state, provincial, national, international, and other applicable laws, rules, and regulations (“Applicable Law”), and your use and disclosure to us of such email addresses complies with Applicable Law.</li><li>You have provided all required notices and obtained all required consents to engage Medium to send emails on your behalf for commercial or marketing purposes, including sending stories or newsletters.</li><li>You have collected the email addresses that you will import directly from the email recipients and have not bought, rented, or otherwise acquired these addresses in any way from any third-party.</li><li>You will not direct Medium to send any emails to any recipient who has unsubscribed from your mailing list either in the Medium settings or “unsubscribe” link in the Medium email itself, or through contacting you off-platform in any other way. For more information, please see our <a href=\"https://help.medium.com/hc/en-us/articles/360059837393\">Help Center article</a>.</li><li>If sending emails using the Medium platform results in significant bounce rates (rate of which email addresses in your list that didn’t receive your email because it was returned by a mail server), recipient complaint rates, or unsubscribe requests in excess of industry standards, or a determination that you have engaged in spam, as defined under our<a href=\"https://policy.medium.com/medium-rules-30e5502c4eb4\"> Rules</a>, then Medium may suspend or terminate your use of this Email Import in Medium’s sole discretion.</li><li>When Medium processes the email addresses you import through the Email Import for the purpose of sending emails on your behalf, Medium is a processor or service provider, as those terms are defined under Applicable Law, and Medium processes those emails in accordance with your instructions and on your behalf.</li><li>Medium will not retain, use, or disclose the email addresses for any purpose, including any commercial purpose, other than for the specific purpose of sending emails on your behalf, or as otherwise permitted by Applicable Law, such as honoring recipient unsubscribe requests.</li></ul><p>Please note that your use of the Email Import is part of Medium services, and you must comply with our legal terms, including the<a href=\"https://policy.medium.com/medium-terms-of-service-9db0094a1e0f\"> Terms of Service</a>,<a href=\"https://policy.medium.com/medium-privacy-policy-f03bf92035c9\"> Privacy Policy</a>, and<a href=\"https://policy.medium.com/medium-rules-30e5502c4eb4\"> Rules</a> at all times. Medium reserves the right to suspend or terminate your access to Medium and its services with or without notice in Medium’s sole discretion</p><p>If you have any questions about this Email Import, please review our <a href=\"https://help.medium.com/hc/en-us/articles/360059837393\">Help Center article</a>.</p><img src=\"https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=cccf29534bf4\" width=\"1\" height=\"1\" alt=\"\"><hr><p><a href=\"https://policy.medium.com/email-import-terms-of-use-cccf29534bf4\">Email Import Terms of Use</a> was originally published in <a href=\"https://policy.medium.com\">Medium Policy</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>"},{"guid":"https://medium.com/p/fcfe9cf777b8","link":"https://policy.medium.com/medium-partner-program-terms-fcfe9cf777b8?source=rss-504c7870fdb6------2","title":"Medium Partner Program Terms","author":"Medium","excerpt":"Effective as of June 1, 2026. These terms (the “Partner Program Terms”) govern A Medium Corporation’s (“Medium”) partner program (“Partner Program”). If you apply, meet the eligibility criteria, and are accepted into Medium’s Partner Program, you can (i) put a story from your user account behind Med","updated":"2026-06-01T20:09:10.689Z","published":"Wed, 11 Aug 2021 23:38:00 GMT","categories":["medium","terms-of-service"],"content_html":"<p><strong>Effective as of June 1, 2026.</strong></p><p>These terms (the “Partner Program Terms”) govern A Medium Corporation’s (“Medium”) partner program (“Partner Program”). If you apply, meet the eligibility criteria, and are accepted into Medium’s Partner Program, you can (i) put a story from your user account behind Medium’s paywall (“locking” a story) and receive revenue based on its performance among Medium members, and (ii) subject to your further evaluation and acceptance by Medium, to participate in the Editor Partner Program, as more specifically defined and described below. Medium reserves the right to modify, suspend, or discontinue the Partner Program, or any portion thereof, at any time and without advance notice to you. Medium will not be liable to you or any third party for any such modification, suspension, or termination.</p><p>By participating in the Partner Program, you agree to these Partner Program Terms, as well as Medium’s <a href=\"https://medium.com/policy/medium-terms-of-service-9db0094a1e0f\">Terms of Service</a>, <a href=\"https://medium.com/policy/medium-privacy-policy-f03bf92035c9\">Privacy Policy</a>, <a href=\"https://medium.com/policy/medium-rules-30e5502c4eb4\">Rules</a>, and all other terms and conditions that apply to the Medium website, mobile applications, and any other Medium service or product (collectively, the “Terms”). Please read the Partner Program Terms carefully. If you don’t understand them, or don’t accept any part of them, then you can’t participate in the Partner Program. Your acceptance of Medium’s Partner Program Terms forms a binding agreement between you and Medium and shows your intent to be bound by them.</p><h3>Eligibility &amp; Application</h3><p>To participate in the Partner Program, you must meet the <a href=\"https://help.medium.com/hc/en-us/articles/115011694187\">Eligibility Requirements</a>, apply, and be accepted into the Partner Program. Medium reserves the right to admit writers to the Partner Program at Medium’s sole discretion. Eligibility requirements are subject to change.</p><p><strong><em>Existing Partner Program Participants</em>:</strong> If you are a participant in the Partner Program as of August 1, 2024, you will remain in the program. However, to continue to participate in the Partner Program, you’ll need to meet the <a href=\"https://help.medium.com/hc/en-us/articles/115011694187\">Eligibility Requirements</a> by December 31, 2024. Medium will use reasonable efforts to contact you before removing you from the Partner Program if you no longer meet the Eligibility Requirements. If you are removed from the Partner Program, your locked stories will be removed from behind the paywall.</p><p><strong><em>Ongoing Eligibility for all Partner Program participants</em>:</strong> To remain in the Partner Program, you must continue to meet the <a href=\"https://help.medium.com/hc/en-us/articles/115011694187\">Eligibility Requirements</a>. In the event that we disable your ability to receive any revenue under the Partner Program and we subsequently determine that you meet the requirements to remain in the Partner Program, we may re-enable your ability to receive revenue under the Partner Program without requiring a reapplication from you for the Partner Program.</p><h3>Earning on Locked Stories</h3><p><strong><em>User Stories<br></em></strong>For each locked story associated with your account, you have the opportunity to receive revenue based on various performance factors, including reader engagement. Based on the performance and assessed quality of a story, Medium will pay you a portion of revenues received by Medium from membership fees, as determined by Medium. Medium will send you payment for any revenues above $10 USD accrued as described in the Payment section below. Medium reserves the right to adjust at any time the factors by which story performance and revenue are determined.</p><p><strong><em>User Stories &amp; Medium Publications<br></em></strong>A locked story may be included in a Medium publication. The writer chooses whether to lock a story and will receive the same amount of funds through the Partner Program regardless of whether the story is included in a publication. As with any story, either the writer or the publication owner or editors may choose to remove a locked story from a publication at any time.</p><p>The above arrangement may be modified on a case-by-case basis, such as for publications operating on Medium that commission or own their content. For any such publication planning to receive proceeds from a story’s performance, this arrangement must be made clear to any writer potentially affected and agreed upon in advance with a given story’s writer.</p><h3>Earning on Editing Activities</h3><p>As a participant in the Partner Program, you will be eligible to apply to participate in Medium’s Editor Partner Program (the “EPP”). Medium reserves the right to admit or reject any applicant to the EPP at Medium’s sole discretion. Eligibility requirements for the EPP are described <a href=\"https://help.medium.com/hc/en-us/articles/40661484998679-Editor-Partner-Program-overview\">here</a> and may be changed by Medium at any time without notice.</p><p>If Medium accepts your application to participate in the EPP, you will be permitted to edit eligible stories submitted to Medium publications of which you are an owner or an editor, in accordance with Medium’s editorial guidelines and policies. For each story you edit, you may earn compensation based on that story’s performance, as described in Medium’s EPP Pay Structure <a href=\"https://help.medium.com/hc/en-us/articles/40661484998679-Editor-Partner-Program-overview\">here</a>. Medium retains sole discretion to determine which stories are eligible for editing under the EPP. Medium reserves the right to modify, suspend, or discontinue the EPP, or any portion thereof, at any time and without advance notice to you.</p><p><strong>Note to Writers</strong><br>Stories submitted to Medium may be edited by an editor participating in EPP. EPP editors may receive compensation from Medium based on the performance of stories they edit. Editor compensation is paid by Medium and does not affect the author’s earnings. By submitting a story to Medium, you acknowledge that your story may be edited by an EPP editor who may earn compensation in connection with your story’s performance.</p><h3>Necessary Rights</h3><p>You may only lock a story (i.e. place it behind Medium’s paywall) if you have sufficient rights to make commercial use of the content in it, including text, video, and audio elements. Medium may require you to provide documentation proving you own sufficient rights to lock a story.</p><p>The consequences of locking stories when you lack the rights to do so or failing to provide adequate documentation upon request include unlocking stories, withholding revenue, suspension, or termination from the Partner Program, and suspension or termination of your Medium account.</p><p>You are not entitled to earn or receive any revenue in connection with your content if one or more third parties claim rights to any element(s) of your content.</p><p>These Partner Terms are not legal advice. If you plan to lock and earn revenue on a story containing any content you did not create, you may want to talk to a lawyer first to ensure you own all rights required to do so.</p><h3>Termination</h3><p>Medium reserves the right to unlock a story at any time, which will end that story’s ability to generate revenue. Medium reserves the right in its sole discretion to disable your ability to receive any revenue under the Partner Program, suspend your participation in the Partner Program, or terminate your participation in the Partner Program at any time for any reason, including but not limited to the failure to meet the Eligibility Requirements, sustained inactivity in the Partner Program, or violation of any terms contained herein.</p><p>If your participation in the Partner Program is terminated for any reason, your locked stories will be unlocked and can no longer generate revenue, and you will no longer be eligible to earn from Medium’s deprecated Referral Earnings program.</p><h3>Payment</h3><p>To accrue or receive payment of any revenues under the Partner Program, you must be a Partner Program participant in good standing (meaning for example, your monetization is not currently disabled, you are not currently suspended, you are not violating Terms or have not violated the Terms, or have not been terminated), have at all times an active Medium account, and have at all times an active payout method associated with your Medium account. Medium does not owe you any revenue that may be associated with your content during any period when you are not in good standing in the Partner Program, do not have a valid Medium account, or do not have an active payout method. You will not receive any revenue if you do not have a payout account in a geographic region where the Partner Program is available. The list of available geographic regions is available <a href=\"https://help.medium.com/hc/en-us/articles/115011694187\">here</a>.</p><p>Medium reserves the right to require that your revenue meet a $10 minimum payout threshold before Medium disburses payment. In the event that you quit or are removed from the Partner Program and have not met the minimum payout threshold OR have not completed your payout settings, Medium reserves the right to forfeit the payment.</p><h3>Changes or Discontinuation of Partner Program</h3><p>Medium reserves the right to modify, suspend, or discontinue the Partner Program. Medium will not be liable to you or any third party for any such modification, suspension, or termination. Medium may change these Partner Program Terms from time to time so we encourage you to periodically review this page for the most up-to-date version.</p><h3>Taxes</h3><p>If required by law, you are responsible for reporting and paying any applicable taxes in connection with your participation in the Partner Program. Such taxes may include duties, customs fees, or other taxes (other than income tax), along with any related penalties or interest.</p><h3>Governing Law &amp; Forum</h3><p>The governing law, mandatory forum, and dispute resolution provisions of Medium’s Terms of Service also apply to these Partner Program Terms and any dispute arising under them.</p><h3>Miscellaneous</h3><p>You participate in the Partner Program at your own risk. You agree that you are solely responsible for your actions in connection with the Partner Program, any breach of your obligations under the Partner Program Terms, and for the consequences of any such breach.</p><p>Any capitalized terms used but not defined in these Partner Program Terms have the meanings given to them in Medium’s Terms of Service. Except as modified by these Partner Program Terms, Medium’s Terms of Service remain in effect. Medium’s right to modify or revise the Terms of Service also applies to these Partner Program Terms.</p><h3>Contact Us</h3><p>If you have questions or feedback about the Partner Program, you can submit a request at help.medium.com.</p><img src=\"https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=fcfe9cf777b8\" width=\"1\" height=\"1\" alt=\"\"><hr><p><a href=\"https://policy.medium.com/medium-partner-program-terms-fcfe9cf777b8\">Medium Partner Program Terms</a> was originally published in <a href=\"https://policy.medium.com\">Medium Policy</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>"},{"guid":"https://medium.com/p/30e5502c4eb4","link":"https://policy.medium.com/medium-rules-30e5502c4eb4?source=rss-504c7870fdb6------2","title":"Medium Rules","author":"Medium","excerpt":"Medium is an open platform that exists to share ideas and perspectives from the world’s most insightful writers, thinkers, and storytellers. We welcome thoughtful and civil discussion from a broad spectrum of viewpoints. To maintain a safe, respectful, and welcoming environment for a wide range of p","updated":"2024-09-24T17:46:09.785Z","published":"Wed, 26 May 2021 07:00:00 GMT","categories":["terms","medium","rules"],"content_html":"<p>Medium is an open platform that exists to share ideas and perspectives from the world’s most insightful writers, thinkers, and storytellers.</p><p>We welcome thoughtful and civil discussion from a broad spectrum of viewpoints. To maintain a safe, respectful, and welcoming environment for a wide range of people to engage in meaningful conversations, we prohibit certain conduct.</p><p>In deciding whether there has been a violation of the rules, we will take into consideration things like<a href=\"https://help.medium.com/hc/en-us/articles/360018664574-Newsworthiness-considerations\"> newsworthiness</a>, the context and nature of the posted information, the likelihood and severity of actual or potential harms, account history, and applicable laws.</p><p>Violations of our rules may result in consequences such as account restrictions or suspension of your content. Medium has the sole authority and final decision as to whether content or behavior violates our rules.</p><h4><strong>To report a violation:</strong></h4><p>If you find a post or account on Medium that you believe violates these rules, <strong>please </strong><a href=\"https://help.medium.com/hc/en-us/articles/217047977-Report-posts-users\"><strong>report it.</strong></a> You can find the report button in the 3-dot menu on every post, response, and account page.</p><p>You can use <a href=\"https://help.medium.com/hc/en-us/requests/new?ticket_form_id=168427\">this form</a> to provide more detail or to report other conduct you believe violates our rules. Additionally, you can send an email to <a href=\"mailto:trust@medium.com\">trust@medium.com</a>.</p><h4><strong>Block and mute:</strong></h4><p>If you find yourself in conflict with another user, we encourage the following:</p><ul><li>Block them and move on. <a href=\"https://help.medium.com/hc/en-us/articles/217048077-Block-a-user\">You can learn more about blocking here</a>.</li><li>Mute them, and they won’t show up in your feeds. <a href=\"https://help.medium.com/hc/en-us/articles/224544048-Mute-an-author-or-publication\">You can learn more about muting here</a>.</li><li>Remove their responses from your stories. <a href=\"https://help.medium.com/hc/en-us/articles/217048127-Manage-responses\">You can learn more about managing and turning off your responses here</a>.</li></ul><h3><strong>Rules</strong></h3><p>Capitalized terms here have the same meaning as defined in the<a href=\"https://policy.medium.com/medium-terms-of-service-9db0094a1e0f\"> Medium Terms of Service</a>.</p><p><strong>Threats of violence and incitement<br></strong>We do not allow content or actions that threaten, encourage, or incite violence against anyone, directly or indirectly.</p><p><strong>Hateful content<br></strong>We do not allow content that constitutes or promotes violence, harassment, or hatred against people based on characteristics like race, ethnicity, national origin, religion, caste, disability, disease, age, sexual orientation, gender, or gender identity.</p><p>We do not allow posts or accounts that glorify, celebrate, downplay, or trivialize violence, suffering, abuse, or deaths of individuals or groups. This includes the use of scientific or pseudoscientific claims or misleading statistics to pathologize, dehumanize, or disempower others. We do not allow calls for intolerance, exclusion, or segregation based on protected characteristics, nor do we allow the glorification of groups which do any of the above.</p><p>We do not allow posts or accounts that target others with slurs, tropes, or other content that intends to dehumanize, degrade or reinforce negative or harmful stereotypes about a protected category. For example, this may include targeted or intentional misgendering or deadnaming of transgender individuals, or harmfully ableist language.</p><p>We do not allow hateful text, images, symbols, or other content, including in your username, profile, or bio.</p><p><strong>Harassment<br></strong>Medium exists to share and discuss ideas. We don’t tolerate harassment, which includes:</p><ul><li>Bullying, threatening, mocking, or shaming someone, or posting things likely to encourage others to do so</li><li>Engaging in a repetitive or targeted campaign of harassment against someone or a group of people</li><li>Using derogatory language, racial slurs, or obscenities to disparage or attack someone or a group of people</li><li>Using Medium features like responses, private notes, mentions, follows, lists, highlights, or requests in a way that attempts to or does annoy or harass someone, or to draw inorganic attention to your content on Medium</li></ul><p><strong>Privacy and Reputation<br></strong>We do not allow the following:</p><ul><li>Posting images of, transcripts of, copies of, or links to private communications between private individuals without the explicit consent of all parties to the communication. Redacting names or other information does not supplant the need to secure permissions</li><li>Doxing, which includes not only private or obscure personal information but also the aggregation of publicly available information to target, shame, blackmail, harass, intimidate, threaten, or endanger a person or group of people</li><li>Posting intimate or explicit images taken or posted without the subject’s express consent</li><li>Content that violates others’ privacy or personal safety, including sensitive or confidential information such as credit card numbers, social security numbers, non-public phone numbers, physical addresses, email addresses, non-public data, or other similar information</li></ul><p><strong>Restricted categories<br></strong>We do not allow posts or accounts that engage in the following restricted categories of activity:</p><ul><li>Promotion of controversial, suspect, or extreme content. <a href=\"https://help.medium.com/hc/en-us/articles/360018182453\">You can read more about these policies in our Help Center</a>.</li><li>Facilitation of gambling or betting</li><li>Facilitation of buying or selling social media interactions, including off-platform</li><li>Facilitation of sexual services</li><li>Facilitation of copyright or other intellectual property violation</li><li>Facilitation or evidence of violating the terms of service of Medium or third party(s)</li><li>Providing reviews of businesses or products in a gratuitously harmful or abusive manner</li><li>Facilitation of illegal hacking (e.g., stealing credentials, compromising personal data)</li><li>Promotion of pseudoscience, disinformation, or other content that is contrary to public health or safety</li></ul><p><strong>Related conduct<br></strong>We do not allow content or accounts that engage in on-platform, off-platform, or cross-platform campaigns of targeting, harassment, hate speech, violence, or disinformation. We may consider off-platform actions in assessing a Medium account, and restrict access or availability to that account.</p><p><strong>Graphic content<br></strong>We do not allow posting, linking to, or otherwise promoting pornographic images or videos. We do allow erotic writing and non-graphic erotic images.</p><p>Medium is a large network, and posts can travel in front of all different types of readers. We ask that you be mindful of unintentional viewers when selecting your images.</p><p>We do not allow gratuitously graphic or disturbing media, regardless of subject matter.</p><p><strong>Exploitation of minors<br></strong>We do not allow content promoting the sexual, violent, or other exploitation of minors, including the sexualization of fictional minors.</p><p><strong>Promotion and glorification of self-harm<br></strong>We do not allow content or activities that encourage, promote or glorify acts of self-harm, such as cutting, eating disorders like anorexia or bulimia, and suicide. If you encounter users contemplating or threatening self-harm, please report it.</p><p><strong>Duplicate Content<br></strong>We do not allow posting <a href=\"https://help.medium.com/hc/en-us/articles/360039513913-About-the-No-Duplicate-Content-rule\">duplicate copies</a> of the same content to Medium, whether from a single account or across multiple accounts, either publicly or as an unlisted story. (You are allowed to cross-post content from your blog to Medium, provided you own the rights for the content.)</p><p><strong>Spam or Site Misuse<br></strong>We do not allow spam or misuse of Medium. All spam or misuse will be immediately removed from Medium without notification. Examples of spam or misuse include:</p><ul><li>Posting content primarily to drive traffic to, or increase the search rankings of, an external site, product, or service</li><li>Scraping and reposting content from other sources for the primary purpose of generating revenue or other personal gains</li><li>Posting duplicate content, whether from a single account or across multiple accounts</li><li>Stories where the content is clipped with the purpose of linking to the rest of the article on a different website</li><li>Performing a disproportionately large number of interactions, particularly by automated means. This includes bulk or indiscriminate interactions, such as following of other accounts (follow spam), clapping, highlighting, leaving notes, or flagging content</li><li>Repeatedly using responses, mentions, or other interactions as a method of promotion or marketing</li><li>Participating in bounty campaigns or brigades to artificially inflate rankings for posts, accounts, businesses, or products</li><li>Use or re-use content templates with slight modifications across multiple posts and accounts</li></ul><p>For each of these behaviors, when we talk about “content,” we mean not only posts but also any other feature that allows you to add your own text or media. When we talk about “interactions,” we mean any feature that allows one user to interact with another person or post.</p><p><strong>Copyright and trademark infringement<br></strong>Respect the copyrights and trademarks of others. Per our<a href=\"https://medium.com/policy/medium-terms-of-service-9db0094a1e0f\"> Terms of Service</a>, we require users to have permission to post the content they publish on Medium. Additionally, we have <a href=\"https://help.medium.com/hc/en-us/articles/360041640213\">specific policies</a> around plagiarism, to which all Medium accounts are held. Users found in violation of our copyright rules are not eligible for warning, appeal, or restoration. Deletion of copyright violations is not grounds for reinstatement.</p><p>We respond to notices of alleged infringement as described in our<a href=\"https://medium.com/policy/medium-terms-of-service-9db0094a1e0f\"> Terms of Service</a>,<a href=\"https://medium.com/policy/mediums-copyright-and-dmca-policy-d126f73695\"> Copyright and DMCA Policy</a>, and<a href=\"https://medium.com/policy/mediums-trademark-policy-e3bb53df59a7\"> Trademark Policy</a>.</p><p><strong>Deceptive conduct<br></strong>We do not allow deceptive conduct on Medium. This includes:</p><ul><li>Posting content or impersonating a person or organization in a way likely to deceive people. Parody and satire are fine, but make clear that is what you’re doing. Our<a href=\"https://medium.com/policy/medium-username-policy-7054a77fb04f\"> Username Policy</a> has specific requirements for parody accounts</li><li>Using Medium for phishing or fraud. Don’t use tags, links, titles, or other metadata in a misleading way. Don’t link to or embed malicious or harmful code or software in your posts</li><li>Using deception to generate revenue or traffic</li><li>If you have received free goods or services, or anything of value in connection with the topic of a post, you must make this clear.</li></ul><p><strong>Ads, Promotions, and Marketing</strong></p><ul><li>First party promotion is allowed, and you may promote and link to your own business, website, mailing list, or fundraiser.</li><li>Third-party advertising and sponsorships are not allowed. You may not advertise or promote third-party products, services, or brands through Medium posts, publications, or newsletters. This includes images that indicate brand sponsorship in a post or newsletter, or as part of a publication name or logo.</li><li>Affiliate links, such as links out to Amazon with an affiliate code, or any other link out where you will receive a commission or other value, are allowed in posts. However, per Federal Trade Commission law, you must disclose the inclusion of these links in your post. This can be a simple sentence in the footer. (for further guidance, see<a href=\"https://www.ftc.gov/tips-advice/business-center/guidance/ftcs-endorsement-guides-what-people-are-asking\"> FTC Rules and Guides</a>).</li></ul><p><strong>Embedded Content and Collection of Personal Information<br></strong>To ensure the data privacy and security of our users, embedded content must comply with the following requirements. An “embed” includes a link, form, or a request for information or other content.</p><p>Embeds directly collecting data through Medium form fields, comments or other onsite means are not allowed. This includes embeds that facilitate the submission of email addresses, credit card information or other personal information. If you want to collect information from your readers, you will need to follow these requirements:</p><ul><li>If you link out from your post on Medium to a form hosted elsewhere, that form must make it clear to a user that they are no longer in the Medium network and the information they disclose is subject to the third-party’s Terms of Use and Privacy Policy,</li><li>If the link directs users to your own platform to subscribe to your newsletter, blog or other content you create, then in your Medium content immediately next to the link you must disclose that the link will take the user offsite outside of Medium</li><li>If your content includes a form that sends user information to you or a third-party, immediately next to or within the form you must disclose that the form will send the user’s information to an offsite third-party outside of Medium that is subject to that offsite third-party’s Terms of Use and Privacy Policy, or offsite outside of Medium, to you directly.</li></ul><p><strong>Paid, automatic, bulk, or non-genuine interactions<br></strong>Medium depends on various user behaviors — like follows and claps — to determine what content to feature and make the site work well for everyone. We don’t allow artificial behaviors that skew this system and as a result degrade or distort other users’ experiences.</p><p>This includes:</p><ul><li>Buying, selling, or trading in accounts or account interactions — including views, reads, follows, claps, highlights, responses, or other traffic</li><li>Using services, apps, or arrangements that offer you more views, reads, follows, claps, or other interactions on your Medium account or content</li><li>Registering accounts, posting content, or interacting with users or content automatically, systematically, or programmatically</li></ul><p><strong>Cryptocurrency Accounts, Posts, and Publications<br></strong>Posts and accounts that are focused on launching, announcing, or providing information on cryptocurrencies must meet the requirements listed in our <a href=\"https://help.medium.com/hc/en-us/articles/360000646167-Cryptocurrencies-on-Medium#:~:text=Medium%20does%20not%20endorse%20or,maintain%20that%20email%20account%20actively.\">Cryptocurrency Policy</a>. Medium does not endorse or verify any coin, token, financial advice, or similar announcement.</p><h4><strong>Prohibitions on Use of the Services</strong></h4><p>You agree not to do, try to do, or cause a third party to do any of the following, except without the express written consent of Medium:</p><p>(1) access or tamper with non-public areas of the Services, our computer systems, or the systems of our technical providers;</p><p>(2) access or search the Services by any means other than the currently available, published interfaces (e.g., APIs) that we provide;</p><p>(3) forge any TCP/IP packet header or any part of the header information in any email or posting, or in any way use the Services to send altered, deceptive, or false source-identifying information;</p><p>(4) use the Services in any manner that could disable, overburden, damage, or impair the Services, or interfere with any other use of the Services;</p><p>(5) use any software, script, robot, spider or other automatic device, process or means (including crawlers, browser plugins and add-ons or any other technology) to access the Services for any purpose, including without limitation to scrape or otherwise copy any of the data or content on the Services;</p><p>(6) use any manual process to monitor or copy any of the data or content on the Services, or to engage in any other unauthorized purpose;</p><p>(7) otherwise use any device, software or routine that interferes with the proper working of the Services; or</p><p>(8) otherwise attempt to interfere with the proper working of the Services.</p><h4><strong>Use of custom domain features</strong></h4><p>Medium provides the ability to point a domain name that you control to a publication on Medium. If you use this custom domain feature, you understand that your publication will still be hosted on Medium and will still be subject to Medium’s Terms of Service. If you use this custom domain feature, you may not do, try to do, or cause a third party to do the following:</p><p>(1) Alter the look and feel or transform the content of the webpage, including by injecting ads, inserting tracking code, or altering the Medium look or feel;</p><p>(2) Use proxy servers or any other means to short-circuit our rules or circumvent user protections; or</p><p>(3) Mislead users about what site they are on or what their actions will do.</p><p>Your use of the custom domain feature must comply with our<a href=\"https://policy.medium.com/medium-privacy-policy-f03bf92035c9\"> Privacy Policy</a>. Please note that our rules around storing, transferring, and using user data are more user-protective than some other sites’. We do not sell user data or allow tracking of our users across the web. We expect you to uphold these same rules and policies in connection with operating your custom domain.</p><h4><strong>How to report a violation</strong></h4><p>If you find a post or account on Medium that violates these rules, please<a href=\"https://help.medium.com/hc/en-us/articles/214098258-Report-posts-users\"> report it</a> in product. You can use<a href=\"https://yourfriends.medium.com/\"> this form</a> to provide more detail or to report other conduct you believe violates our rules. Additionally, you can send us an email to trust@medium.com.</p><h4><strong>If you break the rules</strong></h4><p>We strive to be fair, but we reserve the right to suspend accounts or remove content, without notice, for any reason, particularly to protect our services, infrastructure, users, or community. If you attempt to evade suspension by creating new accounts or posts, we will suspend your new accounts and posts.</p><h4><strong>Notice</strong></h4><p>Upon investigating or disabling content associated with your account, we will notify you, unless we believe your account is automated or operating in bad faith, or that notifying you is likely to cause, maintain or exacerbate harm to someone.</p><h4><strong>Appeals</strong></h4><p>If you believe your content or account has been restricted or disabled in error, or believe there is relevant context we were not aware of in reaching our determination, you can write to us at <a href=\"mailto:trust@medium.com\">trust@medium.com</a>. We will consider all good faith efforts to appeal.</p><h4><strong>Government Takedown Requests</strong></h4><p>If Medium receives a request from a government actor to restrict access to content associated with your account, we will notify you unless we are prohibited by law or believe doing so may endanger others. Where applicable, we will work to limit legally-ordered content restrictions to jurisdictions where we have a good faith belief that we are legally required to restrict the content. Medium submits to the<a href=\"https://www.lumendatabase.org/\"> Lumen</a> database government requests to restrict access to content (redacted where appropriate to protect privacy or prevent harm to a person).</p><p>We may enforce, or not enforce, these policies at our sole discretion. These policies don’t create a duty or contractual obligation for us to act.</p><p>We also may change these rules at any time. We<a href=\"https://github.com/Medium/Policy/blob/master/Rules.md\"> track changes</a> to our rules on Github so you can see how they evolve.</p><p>Medium is committed to providing a transparent, open platform for expression and therefore supports the goals and spirit of<a href=\"https://santaclaraprinciples.org/\"> The Santa Clara Principles on Transparency and Accountability in Content Moderation</a> as a starting point for further discussion.</p><p><em>Updated June 2023</em></p><img src=\"https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=30e5502c4eb4\" width=\"1\" height=\"1\" alt=\"\"><hr><p><a href=\"https://policy.medium.com/medium-rules-30e5502c4eb4\">Medium Rules</a> was originally published in <a href=\"https://policy.medium.com\">Medium Policy</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>"},{"guid":"https://medium.com/p/f03bf92035c9","link":"https://policy.medium.com/medium-privacy-policy-f03bf92035c9?source=rss-504c7870fdb6------2","title":"Medium Privacy Policy","author":"Medium","excerpt":"Effective date: March 24, 2022 You can see our previous Privacy Policy here . This Privacy Policy explains how A Medium Corporation ( “ Medium ,” “ we ,” or “ us ” ) collects, uses, and discloses information about you. This Privacy Policy applies when you use our websites, mobile applications, and o","updated":"2026-05-07T20:03:52.753Z","published":"Tue, 01 Sep 2020 22:57:00 GMT","categories":["medium","privacy"],"content_html":"<h4>Effective date: March 24, 2022</h4><p><strong><em>You can see our previous Privacy Policy </em></strong><a href=\"https://medium.zendesk.com/hc/en-us/articles/360052305234\"><strong><em>here</em></strong></a><strong><em>.</em></strong></p><p>This Privacy Policy explains how A Medium Corporation (<em>“</em><strong><em>Medium</em></strong><em>,”</em> <em>“</em><strong><em>we</em></strong><em>,”</em> or <em>“</em><strong><em>us</em></strong><em>”</em>) collects, uses, and discloses information about you. This Privacy Policy applies when you use our websites, mobile applications, and other online products and services that link to this Privacy Policy (collectively, our <em>“</em><strong><em>Services</em></strong>”), contact our customer service team, engage with us on social media, or otherwise interact with us.</p><p>We may change this Privacy Policy from time to time. If we make changes, we will notify you by revising the date at the top of this policy and, in some cases, we may provide you with additional notice (such as adding a statement to our website or providing you with a notification). We encourage you to review this Privacy Policy regularly to stay informed about our information practices and the choices available to you.</p><h3>CONTENTS</h3><ul><li>Collection of Information</li><li>Use of Information</li><li>Sharing of Information</li><li>Third-Party Embeds</li><li>Transfer of Information to the United States and Other Countries</li><li>Your Choices</li><li>Your California Privacy Rights</li><li>Additional Disclosures for Individuals in Europe</li><li>Contact Us</li></ul><h4>COLLECTION OF INFORMATION</h4><h4>Information You Provide to Us</h4><p>We collect information you provide directly to us. For example, you share information directly with us when you create an account, fill out a form, submit or post content through our Services, purchase a membership, communicate with us via third-party platforms, request customer support, or otherwise communicate with us. The types of personal information we may collect include your name, display name, username, bio, email address, business information, your content, including your avatar image, photos, posts, responses, and series published by you, and any other information you choose to provide.</p><p>In some cases, we may also collect information you provide about others, such as when you purchase a Medium membership as a gift for someone. We will use this information to fulfill your request and will not send communications to your contacts unrelated to your request, unless they separately consent to receive communications from us or otherwise engage with us.</p><p>We do not collect payment information through our Services. We rely on third parties to process payments in connection with our Services. Any information you provide to facilitate such a payment is subject to the third-party payment processor’s privacy policy, and we encourage you to review this policy before you provide any information to the payment processor.</p><h4>Information We Collect Automatically When You Interact with Us</h4><p>In some instances, we automatically collect certain information, including:</p><ul><li><strong>Activity Information:</strong> We collect information about your activity on our Services, such as your reading history and when you share links, follow users, highlight posts, and clap for posts.</li><li><strong>Transactional Information:</strong> When you purchase a membership, we collect information about the transaction, such as subscription details, purchase price, and the date of the transaction.</li><li><strong>Device and Usage Information:</strong> We collect information about how you access our Services, including data about the device and network you use, such as your hardware model, operating system version, mobile network, IP address, unique device identifiers, browser type, and app version. We also collect information about your activity on our Services, such as access times, pages viewed, links clicked, and the page you visited before navigating to our Services.</li><li><strong>Information Collected by Cookies and Similar Tracking Technologies:</strong> We use tracking technologies, such as cookies and web beacons, to collect information about you. Cookies are small data files stored on your hard drive or in device memory that help us improve our Services and your experience, see which areas and features of our Services are popular, and count visits. Web beacons (also known as “pixel tags” or “clear GIFs”) are electronic images that we use on our Services and in our emails to help deliver cookies, count visits, and understand usage. We also work with third party analytics providers who use cookies, web beacons, device identifiers, and other technologies to collect information about your use of our Services and other websites and applications, including your IP address, web browser, mobile network information, pages viewed, time spent on pages or in mobile apps, and links clicked. This information may be used by Medium and others to, among other things, analyze and track data, determine the popularity of certain content, deliver content targeted to your interests on our Services, and better understand your online activity. For more information about cookies and how to disable them, see Your Choices below.</li></ul><h4>Information We Collect from Other Sources</h4><p>We obtain information from third-party sources. For example, we may collect information about you from social networks, accounting services providers and data analytics providers. Additionally, if you create or log into your Medium account through a third-party platform (such as Apple, Facebook, Google, or Twitter), we will have access to certain information from that platform, such as your name, lists of friends or followers, birthday, and profile picture, in accordance with the authorization procedures determined by such platform.</p><h4>Information We Derive</h4><p>We may derive information or draw inferences about you based on the information we collect. For example, we may make inferences about your location based on your IP address or infer reading preferences based on your reading history.</p><h4>USE OF INFORMATION</h4><p>We use the information we collect to provide, maintain, and improve our Services, which includes publishing and distributing user-generated content, personalizing the posts you see and operating our metered paywall. We also use the information we collect to:</p><ul><li>Create and maintain your Medium account;</li><li>Process transactions and send related information, such as confirmations, receipts, and user experience surveys;</li><li>Send you technical notices, security alerts, and support and administrative messages;</li><li>Respond to your comments and questions and provide customer service;</li><li>Communicate with you about new content, products, services, and features offered by Medium and provide other news and information we think will interest you (see Your Choices below for information about how to opt out of these communications at any time);</li><li>Monitor and analyze trends, usage, and activities in connection with our Services;</li><li>Detect, investigate, and prevent security incidents and other malicious, deceptive, fraudulent, or illegal activity and protect the rights and property of Medium and others;</li><li>Debug to identify and repair errors in our Services;</li><li>Comply with our legal and financial obligations; and</li><li>Carry out any other purpose described to you at the time the information was collected.</li></ul><h4>SHARING OF INFORMATION</h4><p>We share personal information in the following circumstances or as otherwise described in this policy:</p><ul><li>We share personal information with other users of the Services. For example, if you use our Services to publish content, post comments or send private notes, certain information about you will be visible to others, such as your name, photo, bio, other account information you may provide, and information about your activities on our Services (e.g., your followers and who you follow, recent posts, claps, highlights, and responses).</li><li>We share personal information with vendors, service providers, and consultants that need access to personal information in order to perform services for us, such as companies that assist us with web hosting, storage, and other infrastructure, analytics, payment processing, fraud prevention and security, customer service, communications, and marketing.</li><li>We may disclose personal information if we believe that disclosure is in accordance with, or required by, any applicable law or legal process, including lawful requests by public authorities to meet national security or law enforcement requirements. If we are going to disclose your personal information in response to legal process, we will give you notice so you can challenge it (for example by seeking court intervention), unless we are prohibited by law or believe doing so may endanger others or cause illegal conduct. We will object to legal requests for information about users of our Services that we believe are improper.</li><li>We may share personal information if we believe that your actions are inconsistent with our <a href=\"https://policy.medium.com/\">user agreements or policies</a>, if we believe that you have violated the law, or if we believe it is necessary to protect the rights, property, and safety of Medium, our users, the public, or others.</li><li>We share personal information with our lawyers and other professional advisors where necessary to obtain advice or otherwise protect and manage our business interests.</li><li>We may share personal information in connection with, or during negotiations concerning, any merger, sale of company assets, financing, or acquisition of all or a portion of our business by another company.</li><li>Personal information is shared between and among Medium and our current and future parents, affiliates, and subsidiaries and other companies under common control and ownership.</li><li>We share personal information with your consent or at your direction.</li><li>We also share aggregated or de-identified information that cannot reasonably be used to identify you.</li></ul><h4>HELPING YOU CONNECT WITH PEOPLE YOU KNOW</h4><p>When you use our address book feature, we process contact information from your device to help you discover people you know who are on Medium.</p><p>Why we do this: We rely on legitimate interests to offer this feature — specifically, our interest in helping you connect with people you know, and our mission to deepen collective understanding through writing, which supports your fundamental right to freedom of expression and information.</p><p>How it works: When you opt in, we convert contact names and email addresses into encrypted, non-reversible identifiers and match them against our member database. We don’t store names or emails in plain text. For contacts who aren’t Medium members, we delete their encrypted identifiers immediately after checking. We delete all encrypted identifiers within 30 days.</p><h4>THIRD-PARTY EMBEDS</h4><p>Medium does not host some of the content displayed on our Services. Users have the ability to post content that is actually hosted by a third party, but is embedded in our pages (an <em>“</em><strong><em>Embed</em></strong><em>”</em>). When you interact with an Embed, it can send information about your interaction to the hosting third party just as if you were visiting the third party’s site directly. For example, when you load a Medium post page with a YouTube video Embed and watch the video, YouTube receives information about your activity, such as your IP address and how much of the video you watch. Medium does not control what information third parties collect through Embeds or what they do with the information. This Privacy Policy does not apply to information collected through Embeds. The privacy policy belonging to the third party hosting the Embed applies to any information the Embed collects, and we recommend you review that policy before interacting with the Embed.</p><h4>TRANSFER OF INFORMATION TO THE UNITED STATES AND OTHER COUNTRIES</h4><p>Medium is headquartered in the United States, and we have operations and service providers in the United States and other countries. Therefore, we and our service providers may transfer your personal information to, or store or access it in, jurisdictions that may not provide levels of data protection that are equivalent to those of your home jurisdiction. For example, we transfer personal data to Amazon Web Services, one of our service providers that processes personal information for us in various data center locations across the globe, including those listed <a href=\"https://aws.amazon.com/about-aws/global-infrastructure/\">here</a>. We will take steps to ensure that your personal information receives an adequate level of protection in the jurisdictions in which we process it.</p><h4>YOUR CHOICES</h4><h4>Account Information</h4><p>You may access, correct, delete and export your account information at any time by logging into the Services and navigating to the<a href=\"https://medium.com/me/settings\"> Settings page</a>. Please note that if you choose to delete your account, we may continue to retain certain information about you as required by law or for our legitimate business purposes.</p><h4>Cookies</h4><p>Most web browsers are set to accept cookies by default. If you prefer, you can usually adjust your browser settings to remove or reject browser cookies. Please note that removing or rejecting cookies could affect the availability and functionality of our Services.</p><h4>Communications Preferences</h4><p>You may opt out of receiving certain communications from us, such as digests, newsletters, and activity notifications, by following the instructions in those communications or through your account’s <a href=\"https://medium.com/me/settings\">Settings page</a>. If you opt out, we may still send you administrative emails, such as those about your account or our ongoing business relations.</p><h4>Mobile Push Notifications</h4><p>With your consent, we may send push notifications to your mobile device. You can deactivate these messages at any time by changing the notification settings on your mobile device.</p><h4>YOUR CALIFORNIA PRIVACY RIGHTS</h4><p>The California Consumer Privacy Act or <em>“</em><strong><em>CCPA</em></strong><em>”</em> (Cal. Civ. Code § 1798.100 et seq.) affords consumers residing in California certain rights with respect to their personal information. If you are a California resident, this section applies to you.</p><p>In the preceding 12 months, we have collected the following categories of personal information: identifiers, commercial information, internet or other electronic network activity information, and inferences. For details about the precise data points we collect and the categories of sources of such collection, please see the Collection of Information section above. We collect personal information for the business and commercial purposes described in the Use of Information section above. In the preceding 12 months, we have disclosed the following categories of personal information for business purposes to the following categories of recipients:</p><figure><img alt=\"\" src=\"https://cdn-images-1.medium.com/max/646/0*b9fTh2C5b0m9HrZm\" /></figure><p><a href=\"https://medium.com/@Medium/categories-of-personal-information-917cda14ca49\">Link to a text version of this table</a></p><p>Medium does not sell your personal information.</p><p>Subject to certain limitations, you have the right to (1) request to know more about the categories and specific pieces of personal information we collect, use, and disclose about you, (2) request deletion of your personal information, (3) opt out of any sales of your personal information, if we engage in that activity in the future, and (4) not be discriminated against for exercising these rights. You may make these requests by emailing us at <a href=\"mailto:privacy@medium.com\">privacy@medium.com</a> or by completing <a href=\"https://help.medium.com/hc/en-us/requests/new#/360002298134/360051136954/\">this webform</a>. We will verify a webform request by asking you to provide identifying information. We will not discriminate against you if you exercise your rights under the CCPA.</p><p>If we receive your request from an authorized agent, we may ask for evidence that you have provided such agent with a power of attorney or that the agent otherwise has valid written authority to submit requests to exercise rights on your behalf. This may include requiring you to verify your identity. If you are an authorized agent seeking to make a request, please <a href=\"mailto:privacy@medium.com\">contact us</a>.</p><h4>ADDITIONAL DISCLOSURES FOR INDIVIDUALS IN EUROPE</h4><p>If you are located in the European Economic Area (<em>“</em><strong><em>EEA</em></strong><em>”</em>), the United Kingdom, or Switzerland, you have certain rights and protections under applicable law regarding the processing of your personal data, and this section applies to you.</p><h4>Legal Basis for Processing</h4><p>When we process your personal data, we will do so in reliance on the following lawful bases:</p><ul><li>To perform our responsibilities under our contract with you (e.g., providing the products and services you requested).</li><li>When we have a legitimate interest in processing your personal data to operate our business or protect our interests (e.g., to provide, maintain, and improve our products and services, conduct data analytics, and communicate with you).</li><li>To comply with our legal obligations (e.g., to maintain a record of your consents and track those who have opted out of non-administrative communications).</li><li>When we have your consent to do so (e.g., when you opt in to receive non-administrative communications from us). When consent is the legal basis for our processing your personal data, you may withdraw such consent at any time.</li></ul><h4>Data Retention</h4><p>We store personal data associated with your account for as long as your account remains active. If you close your account, we will delete your account data within 14 days. We store other personal data for as long as necessary to carry out the purposes for which we originally collected it and for other legitimate business purposes, including to meet our legal, regulatory, or other compliance obligations.</p><h4>Data Subject Requests</h4><p>Subject to certain limitations, you have the right to request access to the personal data we hold about you and to receive your data in a portable format, the right to ask that your personal data be corrected or erased, and the right to object to, or request that we restrict, certain processing. To exercise your rights:</p><ul><li>If you sign up for a Medium account, you may at any time request an export of your personal information from the <a href=\"https://medium.com/me/settings\">Settings page</a>, or by going to Settings and then selecting Account within our app.</li><li>You may correct information associated with your account from the <a href=\"https://medium.com/me/settings\">Settings page</a>, or by going to Settings and then selecting Account within our app, and the <a href=\"https://medium.com/me/following/suggestions\">Customize Your Interests page</a> to update your interests.</li><li>You may withdraw consent by deleting your account at any time through the <a href=\"https://medium.com/me/settings\">Settings page</a>, or by going to Settings and then selecting Account within our app (except to the extent Medium is prevented by law from deleting your information).</li><li>You may object at any time to the use of your personal data by contacting <a href=\"mailto:privacy@medium.com\">privacy@medium.com</a>.</li></ul><h4>Questions or Complaints</h4><p>If you have a concern about our processing of personal data that we are not able to resolve, you have the right to lodge a complaint with the Data Protection Authority where you reside. Contact details for your Data Protection Authority can be found using the links below:</p><ul><li>For individuals in the EEA:<br><a href=\"https://edpb.europa.eu/about-edpb/board/members_en\">https://edpb.europa.eu/about-edpb/board/members_en</a></li><li>For individuals in the UK:<br><a href=\"https://ico.org.uk/global/contact-us/\">https://ico.org.uk/global/contact-us/</a></li><li>For individuals in Switzerland: <a href=\"https://www.edoeb.admin.ch/edoeb/en/home/the-fdpic/contact.html\">https://www.edoeb.admin.ch/edoeb/en/home/the-fdpic/contact.html</a></li></ul><h4>CONTACT US</h4><p>If you have any questions about this Privacy Policy, please contact us at <a href=\"mailto:privacy@medium.com\">privacy@medium.com</a>.</p><p>If you are from the EEA or the United Kingdom and have questions about this Privacy Policy, please contact us at <a href=\"mailto:privacy@medium.com\">privacy@medium.com</a> or our privacy representatives as follows:</p><h4>Privacy representative for EEA</h4><p>Unit 3D North Point House<br>North Point Business Park<br>New Mallow Road<br>Cork T23AT2P<br>Ireland</p><p>Or <a href=\"https://verasafe.com/public-resources/contact-data-protection-representative\">here</a>.</p><h4>Privacy representative for the United Kingdom</h4><p>37 Albert Embankment<br>London SE1 7TL<br>United Kingdom</p><p>Or <a href=\"https://verasafe.com/public-resources/contact-data-protection-representative\">here</a>.</p><img src=\"https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=f03bf92035c9\" width=\"1\" height=\"1\" alt=\"\"><hr><p><a href=\"https://policy.medium.com/medium-privacy-policy-f03bf92035c9\">Medium Privacy Policy</a> was originally published in <a href=\"https://policy.medium.com\">Medium Policy</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>"},{"guid":"https://medium.com/p/9db0094a1e0f","link":"https://policy.medium.com/medium-terms-of-service-9db0094a1e0f?source=rss-504c7870fdb6------2","title":"Medium Terms of Service","author":"Medium","excerpt":"Effective: September 1, 2020 You can see our previous Terms here . Thanks for using Medium. Our mission is to deepen people’s understanding of the world and spread ideas that matter. These Terms of Service (“ Terms ”) apply to your access to and use of the websites, mobile applications and other onl","updated":"2026-05-12T19:40:11.374Z","published":"Tue, 01 Sep 2020 22:54:00 GMT","categories":["medium","terms","terms-and-conditions"],"content_html":"<h4><strong>Effective: September 1, 2020</strong></h4><p><strong><em>You can see our previous Terms </em></strong><a href=\"https://help.medium.com/hc/en-us/articles/360053078253\"><strong><em>here</em></strong></a><strong><em>.</em></strong></p><p>Thanks for using Medium. Our mission is to deepen people’s understanding of the world and spread ideas that matter.</p><p>These Terms of Service (“<strong><em>Terms</em></strong>”) apply to your access to and use of the websites, mobile applications and other online products and services (collectively, the “<strong><em>Services</em></strong>”) provided by A Medium Corporation (“<strong><em>Medium</em></strong>” or “<strong><em>we</em></strong>”). <strong>By clicking your consent (e.g. “Continue,” “Sign-in,” or “Sign-up,”) or by using our Services, you agree to these Terms, including the mandatory arbitration provision and class action waiver in the Resolving Disputes; Binding Arbitration Section.</strong></p><p>Our <a href=\"https://policy.medium.com/medium-privacy-policy-f03bf92035c9\">Privacy Policy</a> explains how we collect and use your information while our <a href=\"https://policy.medium.com/medium-rules-30e5502c4eb4\">Rules</a> outline your responsibilities when using our Services. By using our Services, you’re agreeing to be bound by these Terms and our Rules. Please see our <a href=\"https://policy.medium.com/medium-privacy-policy-f03bf92035c9\">Privacy Policy</a> for information about how we collect, use, share and otherwise process information about you.</p><p>If you have any questions about these Terms or our Services, please contact us at <a href=\"mailto:legal@medium.com\">legal@medium.com</a>.</p><h3>Your Account and Responsibilities</h3><p>You’re responsible for your use of the Services and any content you provide, including compliance with applicable laws. Content on the Services may be protected by others’ intellectual property rights. Please don’t copy, upload, download, or share content unless you have the right to do so.</p><p>Your use of the Services must comply with our Rules.</p><p>You may need to register for an account to access some or all of our Services. Help us keep your account protected. Safeguard your password to the account, and keep your account information current. We recommend that you do not share your password with others.</p><p>If you’re accepting these Terms and using the Services on behalf of someone else (such as another person or entity), you represent that you’re authorized to do so, and in that case the words “you” or “your” in these Terms include that other person or entity.</p><p>To use our Services, you must be at least 13 years old.</p><p>If you use the Services to access, collect, or use personal information about other Medium users (“Personal Information”), you agree to do so in compliance with applicable laws. You further agree not to sell any Personal Information, where the term “sell” has the meaning given to it under applicable laws.</p><p>For Personal Information you provide to us, you represent and warrant that you have lawfully collected the Personal Information and that you or a third party has provided all required notices and collected all required consents before collecting the Personal Information. You further represent and warrant that Medium’s use of such Personal Information in accordance with the purposes for which you provided us the Personal Information will not violate, misappropriate or infringe any rights of another (including intellectual property rights or privacy rights) and will not cause us to violate any applicable laws.</p><h3>User Content on the Services</h3><p>Medium may review your conduct and content for compliance with these Terms and our Rules, and reserves the right to remove any violating content.</p><p>Medium reserves the right to delete or disable content alleged to be infringing the intellectual property rights of others, and to terminate accounts of repeat infringers. We respond to notices of alleged copyright infringement if they comply with the law; please report such notices using our <a href=\"https://help.medium.com/hc/en-us/articles/214120487-Copyright-DMCA-Policy\">Copyright Policy</a>.</p><h3>Rights and Ownership</h3><p>You retain your rights to any content you submit, post or display on or through the Services. <br><br>Unless otherwise agreed in writing, by submitting, posting, or displaying content on or through the Services, you grant Medium a nonexclusive, royalty-free, worldwide, fully paid, and sublicensable license to use, reproduce, modify, adapt, publish, translate, create derivative works from, distribute, publicly perform and display your content and any name, username or likeness provided in connection with your content in all media formats and distribution methods now known or later developed on the Services.</p><p>Medium needs this license because you own your content and Medium therefore can’t display it across its various surfaces (i.e., mobile, web) without your permission.</p><p>This type of license also is needed to distribute your content across our Services. For example, you post a story on Medium. It is reproduced as versions on both our website and app, and distributed to multiple places within Medium, such as the homepage or reading lists. A modification might be that we show a snippet of your work (and not the full post) in a preview, with attribution to you. A derivative work might be a list of top authors or quotes on Medium that uses portions of your content, again with full attribution. This license applies to our Services only, and does not grant us any permissions outside of our Services.</p><p>So long as you comply with these Terms, Medium gives you a limited, personal, non-exclusive, and non-assignable license to access and use our Services.</p><p>The Services are protected by copyright, trademark, and other US and foreign laws. These Terms don’t grant you any right, title or interest in the Services, other users’ content on the Services, or Medium trademarks, logos or other brand features.</p><p>Separate and apart from the content you submit, post or display on our Services, we welcome feedback, including any comments, ideas and suggestions you have about our Services. We may use this feedback for any purpose, in our sole discretion, without any obligation to you. We may treat feedback as nonconfidential.</p><p>We may stop providing the Services or any of its features within our sole discretion. We also retain the right to create limits on use and storage and may remove or limit content distribution on the Services.</p><h3>Termination</h3><p>You’re free to stop using our Services at any time. We reserve the right to suspend or terminate your access to the Services with or without notice.</p><h3>Transfer and Processing Data</h3><p>In order for us to provide our Services, you agree that we may process, transfer and store information about you in the US and other countries, where you may not have the same rights and protections as you do under local law.</p><h3>Indemnification</h3><p>To the fullest extent permitted by applicable law, you will indemnify, defend and hold harmless Medium, and our officers, directors, agents, partners and employees (individually and collectively, the <em>“Medium Parties”</em>) from and against any losses, liabilities, claims, demands, damages, expenses or costs (<em>“Claims”</em>) arising out of or related to your violation, misappropriation or infringement of any rights of another (including intellectual property rights or privacy rights) or your violation of the law. You agree to promptly notify Medium Parties of any third-party Claims, cooperate with Medium Parties in defending such Claims and pay all fees, costs and expenses associated with defending such Claims (including attorneys’ fees). You also agree that the Medium Parties will have control of the defense or settlement, at Medium’s sole option, of any third-party Claims.</p><h3>Disclaimers — Service is “As Is”</h3><p><strong>Medium aims to give you great Services but there are some things we can’t guarantee. Your use of our Services is at your sole risk. You understand that our Services and any content posted or shared by users on the Services are provided “as is” and “as available” without warranties of any kind, either express or implied, including implied warranties of merchantability, fitness for a particular purpose, title, and non-infringement. In addition, Medium doesn’t represent or warrant that our Services are accurate, complete, reliable, current or error-free. No advice or information obtained from Medium or through the Services will create any warranty or representation not expressly made in this paragraph. Medium may provide information about third-party products, services, activities or events, or we may allow third parties to make their content and information available on or through our Services (collectively, “<em>Third-Party Content</em>”). We do not control or endorse, and we make no representations or warranties regarding, any Third-Party Content. You access and use Third-Party Content at your own risk. Some locations don’t allow the disclaimers in this paragraph and so they might not apply to you.</strong></p><h3>Limitation of Liability</h3><p><strong>We don’t exclude or limit our liability to you where it would be illegal to do so; this includes any liability for the gross negligence, fraud or intentional misconduct of Medium or the other Medium Parties in providing the Services. In countries where the following types of exclusions aren’t allowed, we’re responsible to you only for losses and damages that are a reasonably foreseeable result of our failure to use reasonable care and skill or our breach of our contract with you. This paragraph doesn’t affect consumer rights that can’t be waived or limited by any contract or agreement.</strong></p><p><strong>In countries where exclusions or limitations of liability are allowed, Medium and Medium Parties won’t be liable for:</strong></p><p><strong>(a)</strong> <strong>Any indirect, consequential, exemplary, incidental, punitive, or special damages, or any loss of use, data or profits, under any legal theory, even if Medium or the other Medium Parties have been advised of the possibility of such damages.</strong></p><p><strong>(b)</strong> <strong>Other than for the types of liability we can’t limit by law (as described in this section), we limit the total liability of Medium and the other Medium Parties for any claim arising out of or relating to these Terms or our Services, regardless of the form of the action, to the greater of $50.00 USD or the amount paid by you to use our Services.</strong></p><h3>Resolving Disputes; Binding Arbitration</h3><p>We want to address your concerns without needing a formal legal case. Before filing a claim against Medium, you agree to contact us and attempt to resolve the claim informally by sending a written notice of your claim by email at legal@medium.com or by certified mail addressed to A Medium Corporation, 3500 South DuPont Highway Suite IQ-101 Dover, DE 19901. The notice must (a) include your name, residence address, email address, and telephone number; (b) describe the nature and basis of the claim; and (c) set forth the specific relief sought. Our notice to you will be sent to the email address associated with your online account and will contain the information described above. If we can’t resolve matters within thirty (30) days after any notice is sent, either party may initiate a formal proceeding.</p><p><strong>Please read the following section carefully because it requires you to arbitrate certain disputes and claims with Medium and limits the manner in which you can seek relief from us, unless you opt out of arbitration by following the instructions set forth below. No class or representative actions or arbitrations are allowed under this arbitration provision. In addition, arbitration precludes you from suing in court or having a jury trial.</strong></p><p>(a) <strong>No Representative Actions. You and Medium agree that any dispute arising out of or related to these Terms or our Services is personal to you and Medium and that any dispute will be resolved solely through individual action, and will not be brought as a class arbitration, class action or any other type of representative proceeding.</strong></p><p>(b) <strong>Arbitration of Disputes. </strong>Except for small claims disputes in which you or Medium seeks to bring an individual action in small claims court located in the county where you reside or disputes in which you or Medium seeks injunctive or other equitable relief for the alleged infringement or misappropriation of intellectual property, <strong>you and Medium waive your rights to a jury trial and to have any other dispute arising out of or related to these Terms or our Services, including claims related to privacy and data security, (collectively, “<em>Disputes</em>”) resolved in court</strong>. All Disputes submitted to JAMS will be resolved through confidential, binding arbitration before one arbitrator. Arbitration proceedings will be held in San Francisco, California unless you’re a consumer, in which case you may elect to hold the arbitration in your county of residence. For purposes of this section a “<strong><em>consumer</em></strong>” means a person using the Services for personal, family or household purposes. You and Medium agree that Disputes will be held in accordance with the JAMS Streamlined Arbitration Rules and Procedures (“<strong><em>JAMS Rules</em></strong>”). The most recent version of the JAMS Rules are available on the<a href=\"https://www.jamsadr.com/rules-streamlined-arbitration/\"> JAMS website</a> and are incorporated into these Terms by reference. You either acknowledge and agree that you have read and understand the JAMS Rules or waive your opportunity to read the JAMS Rules and waive any claim that the JAMS Rules are unfair or should not apply for any reason.</p><p>(c) You and Medium agree that these Terms affect interstate commerce and that the enforceability of this section will be substantively and procedurally governed by the Federal Arbitration Act, 9 U.S.C. § 1, <em>et seq</em>. (the “<strong><em>FAA</em></strong>”), to the maximum extent permitted by applicable law. As limited by the FAA, these Terms and the JAMS Rules, the arbitrator will have exclusive authority to make all procedural and substantive decisions regarding any Dispute and to grant any remedy that would otherwise be available in court, including the power to determine the question of arbitrability. The arbitrator may conduct only an individual arbitration and may not consolidate more than one individual’s claims, preside over any type of class or representative proceeding or preside over any proceeding involving more than one individual.</p><p>(d) The arbitration will allow for the discovery or exchange of non-privileged information relevant to the Dispute. The arbitrator, Medium, and you will maintain the confidentiality of any arbitration proceedings, judgments and awards, including information gathered, prepared and presented for purposes of the arbitration or related to the Dispute(s) therein. The arbitrator will have the authority to make appropriate rulings to safeguard confidentiality, unless the law provides to the contrary. The duty of confidentiality doesn’t apply to the extent that disclosure is necessary to prepare for or conduct the arbitration hearing on the merits, in connection with a court application for a preliminary remedy, or in connection with a judicial challenge to an arbitration award or its enforcement, or to the extent that disclosure is otherwise required by law or judicial decision.</p><p>(e) You and Medium agree that for any arbitration you initiate, you will pay the filing fee (up to a maximum of $250 if you are a consumer), and Medium will pay the remaining JAMS fees and costs. For any arbitration initiated by Medium, Medium will pay all JAMS fees and costs. You and Medium agree that the state or federal courts of the State of California and the United States sitting in San Francisco, California have exclusive jurisdiction over any appeals and the enforcement of an arbitration award.</p><p>(f) <strong>Any Dispute must be filed within one year after the relevant claim arose; otherwise, the Dispute is permanently barred, which means that you and Medium will not have the right to assert the claim.</strong></p><p>(g) <strong>You have the right to opt out of binding arbitration within 30 days of the date you first accepted the terms of this section by sending an email of your request to trust@medium.com</strong>. In order to be effective, the opt-out notice must include your full name and address and clearly indicate your intent to opt out of binding arbitration. By opting out of binding arbitration, you are agreeing to resolve Disputes in accordance with the next section regarding “Governing Law and Venue.”</p><p>(h) If any portion of this section is found to be unenforceable or unlawful for any reason, (1) the unenforceable or unlawful provision shall be severed from these Terms; (2) severance of the unenforceable or unlawful provision shall have no impact whatsoever on the remainder of this section or the parties’ ability to compel arbitration of any remaining claims on an individual basis pursuant to this section; and (3) to the extent that any claims must therefore proceed on a class, collective, consolidated, or representative basis, such claims must be litigated in a civil court of competent jurisdiction and not in arbitration, and the parties agree that litigation of those claims shall be stayed pending the outcome of any individual claims in arbitration. Further, if any part of this section is found to prohibit an individual claim seeking public injunctive relief, that provision will have no effect to the extent such relief is allowed to be sought out of arbitration, and the remainder of this section will be enforceable.</p><h3><strong>Governing Law and Venue</strong></h3><p>These Terms and any dispute that arises between you and Medium will be governed by California law except for its conflict of law principles. Any dispute between the parties that’s not subject to arbitration or can’t be heard in small claims court will be resolved in the state or federal courts of California and the United States, respectively, sitting in San Francisco, California.</p><p>Some countries have laws that require agreements to be governed by the local laws of the consumer’s country. This paragraph doesn’t override those laws.</p><h3>Amendments</h3><p>We may make changes to these Terms from time to time. If we make changes, we’ll provide you with notice of them by sending an email to the email address associated with your account, offering an in-product notification, or updating the date at the top of these Terms. Unless we say otherwise in our notice, the amended Terms will be effective immediately, and your continued use of our Services after we provide such notice will confirm your acceptance of the changes. If you don’t agree to the amended Terms, you must stop using our Services.</p><h3>Severability</h3><p>If any provision or part of a provision of these Terms is unlawful, void or unenforceable, that provision or part of the provision is deemed severable from these Terms and does not affect the validity and enforceability of any remaining provisions.</p><h3>Miscellaneous</h3><p>Medium’s failure to exercise or enforce any right or provision of these Terms will not operate as a waiver of such right or provision. These Terms, and the terms and policies listed in the Other Terms and Policies that May Apply to You Section, reflect the entire agreement between the parties relating to the subject matter hereof and supersede all prior agreements, statements and understandings of the parties. The section titles in these Terms are for convenience only and have no legal or contractual effect. Use of the word “including” will be interpreted to mean “including without limitation.” Except as otherwise provided herein, these Terms are intended solely for the benefit of the parties and are not intended to confer third-party beneficiary rights upon any other person or entity. You agree that communications and transactions between us may be conducted electronically.</p><h3><strong>Other Terms and Policies that May Apply to You</strong></h3><p>- <a href=\"https://policy.medium.com/medium-rules-30e5502c4eb4\">Medium Rules</a><br>- <a href=\"https://policy.medium.com/medium-partner-program-terms-fcfe9cf777b8\">Partner Program Terms</a><br>- <a href=\"https://policy.medium.com/paid-terms-of-service-cc7f8e165178\">Membership Terms of Service</a><br>- <a href=\"https://policy.medium.com/medium-username-policy-7054a77fb04f\">Username Policy</a><br>- Amendment to Medium Terms of Service Applicable to U.S. Government Users</p><img src=\"https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=9db0094a1e0f\" width=\"1\" height=\"1\" alt=\"\"><hr><p><a href=\"https://policy.medium.com/medium-terms-of-service-9db0094a1e0f\">Medium Terms of Service</a> was originally published in <a href=\"https://policy.medium.com\">Medium Policy</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>"},{"guid":"https://medium.com/p/bad566e3f7da","link":"https://medium.com/blog/clarifying-mediums-new-terms-of-service-bad566e3f7da?source=rss-504c7870fdb6------2","title":"Clarifying Medium’s new Terms of Service","author":"Medium","excerpt":"We appreciate the feedback about the language in our updated Terms of Service that focuses on your content rights. We first responded by preparing a short blog post explaining the updates. We’ve now edited the Terms of Service to more clearly reflect what we said in that post. Here’s the passage we’","updated":"2020-08-20T01:43:17.837Z","published":"Thu, 20 Aug 2020 01:21:16 GMT","categories":["ｍedium","terms-of-service"],"content_html":"<p>We appreciate the feedback about the language in our updated Terms of Service that focuses on your content rights. We first responded by preparing a <a href=\"https://blog.medium.com/our-updated-terms-and-privacy-policy-d03bed9978d8\">short blog post</a> explaining the updates.</p><p>We’ve now edited the <a href=\"https://policy.medium.com/medium-terms-of-service-9db0094a1e0f\">Terms of Service</a> to more clearly reflect what we said in that post.</p><p>Here’s the passage we’ve updated:</p><blockquote><strong>Rights and Ownership</strong></blockquote><blockquote>You retain your rights to any content you submit, post or display on or through the Services.</blockquote><blockquote>Unless otherwise agreed in writing, by submitting, posting, or displaying content on or through the Services, you grant Medium a nonexclusive, royalty-free, worldwide, fully paid, and sublicensable license to use, reproduce, modify, adapt, publish, translate, create derivative works from, distribute, publicly perform and display your content and any name, username or likeness provided in connection with your content in all media formats and distribution methods now known or later developed on the Services.</blockquote><blockquote>Medium needs this license because you own your content and Medium therefore can’t display it across its various surfaces (i.e., mobile, web) without your permission.</blockquote><blockquote>This type of license also is needed to distribute your content across our Services. For example, you post a story on Medium. It is reproduced as versions on both our website and app, and distributed to multiple places within Medium, such as the homepage or reading lists. A modification might be that we show a snippet of your work (and not the full post) in a preview, with attribution to you. A derivative work might be a list of top authors or quotes on Medium that uses portions of your content, again with full attribution. This license applies to our Services only, and does not grant us any permissions outside of our Services.</blockquote><p>This license doesn’t give Medium permission to sell your content to a third party, and we’ll never do that. You’re not granting us permission to use your content outside of Medium. You’re also not granting us copyright to, or ownership of, your content. So, for example, we’ll never claim the right to develop your content into materials such as books, films, or television shows without your knowledge and express consent.</p><p>You’ll notice this license is royalty-free. This means posting to our services doesn’t involve any compensation to you (unless you’re in our Partner Program), just as you wouldn’t get compensated for posting to Twitter, Facebook, or LinkedIn.</p><p>And speaking of our Partner Program, these Terms of Service (just like the previous version of Medium’s Terms of Service) do <strong>not</strong> alter, modify, or supersede that program. All content you decide to put behind our paywall for monetization still earns you money based on subscribed Medium Member engagement. We’re not de-monetizing that content or changing the Partner Program terms.</p><p>To restate:</p><ul><li>You own all the content you post on Medium, and we make no claims to it, nor will we ever in the future.</li><li>We do not, and will not, sell your content or information. Ever.</li></ul><p>If you have any further questions, the best way to contact us is by emailing <a href=\"mailto:yourfriends@medium.com\">yourfriends@medium.com</a>.</p><img src=\"https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=bad566e3f7da\" width=\"1\" height=\"1\" alt=\"\"><hr><p><a href=\"https://medium.com/blog/clarifying-mediums-new-terms-of-service-bad566e3f7da\">Clarifying Medium’s new Terms of Service</a> was originally published in <a href=\"https://medium.com/blog\">The Medium Blog</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>"},{"guid":"https://medium.com/p/d03bed9978d8","link":"https://medium.com/blog/our-updated-terms-and-privacy-policy-d03bed9978d8?source=rss-504c7870fdb6------2","title":"Our Updated Terms and Privacy Policy","author":"Medium","excerpt":"**Edit 8/19/20: We have updated the language in the terms for more clarification. You can read more here: Clarifying Medium’s new Terms of Service You may have noticed a banner across all of Medium notifying you of our upcoming new Terms of Service and Privacy Policy. We’ve received some questions a","updated":"2020-08-20T01:34:01.849Z","published":"Tue, 18 Aug 2020 20:21:17 GMT","categories":["privacy","ｍedium","medium","terms"],"content_html":"<p>**Edit 8/19/20: We have updated the language in the terms for more clarification. You can read more here:</p><p><a href=\"https://blog.medium.com/clarifying-mediums-new-terms-of-service-bad566e3f7da\">Clarifying Medium’s new Terms of Service</a></p><p>You may have noticed a banner across all of Medium notifying you of our upcoming new Terms of Service and Privacy Policy. We’ve received some questions about the updates, so we’d like to give you more context and information about them.</p><p>While some of the language in these policies has changed, Medium’s fundamental beliefs (and behaviors) have not. Here’s the deal:</p><ul><li><strong>You own all the content you post on Medium, and we make no claims to it, nor will we ever in the future.</strong></li><li><strong>We do not, and will not, sell your information. Ever.</strong></li></ul><p>Here are links to our latest <a href=\"https://policy.medium.com/medium-terms-of-service-9db0094a1e0f\">Terms of Service</a> and <a href=\"https://policy.medium.com/medium-privacy-policy-f03bf92035c9\">Privacy Policy</a>. These go into effect on September 1st, 2020. Until that date, our existing Terms and Privacy Policy remain in effect. The purpose of the banner you’ve seen is to give you a heads-up about upcoming changes plus an opportunity to think about them and ask questions.</p><p>The following section in the new Terms of Service does have updated, but not materially new, language:</p><blockquote><strong>Rights and Ownership</strong></blockquote><blockquote>You retain your rights to any content you submit, post or display on or through the Services.</blockquote><blockquote>Unless otherwise agreed in writing, by submitting, posting, or displaying content on or through the Services, you grant Medium a nonexclusive, royalty-free, worldwide, fully paid, and sublicensable license to use, reproduce, modify, adapt, publish, translate, create derivative works from, distribute, publicly perform and display your content and any name, username or likeness provided in connection with your content in all media formats and distribution methods now known or later developed without compensation to you.</blockquote><p>This is the same as the permissions in our Terms’ previous version. It’s just written in different language that’s more precise.</p><p>What this term means is that you’re <strong>granting us a license</strong> to reproduce the content you post on Medium within the surfaces and products <strong>served by Medium only</strong>. These are the referenced “Medium Services.” These services include our website, our official apps, and any other future product or service that is powered by the Medium network.</p><p>You are NOT granting us permission to use your content outside of the Medium network. You also are NOT granting us copyright to or ownership of your content. For example, we would make no claim of ownership over your copyright content for development into any other materials such as books, films, or television shows without your permission and participation.</p><p>Additionally, nothing about our updated Terms changes or overrides your ability to monetize any content you choose to publish into our Partner Program. Nothing is changing with the Partner Program.</p><blockquote>In short, you still 100% own your content, and you remain in control of it.</blockquote><p>You’re just granting us permission to display it on Medium. If you don’t agree to that, you’re free to export your content at any time from your <a href=\"http://medium.com/me/settings\">Settings Page</a>, and you retain complete ownership over it. You can also delete your account on that same page.</p><p>Additionally, we have moved the language regarding sale of your information from the Terms to our <a href=\"https://policy.medium.com/medium-privacy-policy-f03bf92035c9\">Privacy Policy</a>. But it remains the same:</p><blockquote><strong>Medium does not sell your personal information.</strong></blockquote><p>Ever. Full stop. We have made a commitment to be an ad-free platform and, as such, we will not sell your information.</p><p>Additionally, we have clarified CCPA compliance and rights for California residents to our Privacy Policy, and added the option for all users to opt-out of binding arbitration in our Terms of Service.</p><p>Medium continues to respect and promote the rights of creators and users, and we stand firm in our commitment that you alone own and control your work and your data.</p><p>If you have any further questions, please send us an email to <a href=\"mailto:yourfriends@medium.com\">yourfriends@medium.com</a>.</p><img src=\"https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=d03bed9978d8\" width=\"1\" height=\"1\" alt=\"\"><hr><p><a href=\"https://medium.com/blog/our-updated-terms-and-privacy-policy-d03bed9978d8\">Our Updated Terms and Privacy Policy</a> was originally published in <a href=\"https://medium.com/blog\">The Medium Blog</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>"},{"guid":"https://medium.com/p/503dd91c2edd","link":"https://medium.com/blog/medium-the-diversity-report-503dd91c2edd?source=rss-504c7870fdb6------2","title":"Medium: The Diversity Report","author":"Medium","excerpt":"2018 Edition We believe that having diverse perspectives and voices within our workforce is vital for us to offer diverse perspectives and voices to our readers, and the only way to have meaningful diversity at work is to foster an inclusive environment. Diversity for us includes, but is not limited","updated":"2019-01-25T20:36:51.935Z","published":"Fri, 25 Jan 2019 18:14:07 GMT","categories":["diversity","company-culture","inclusion"],"content_html":"<h4>2018 Edition</h4><figure><img alt=\"\" src=\"https://cdn-images-1.medium.com/max/1024/1*N-u0fshAxKzms88RzWfGaw.png\" /></figure><p>We believe that having diverse perspectives and voices within our workforce is vital for us to offer diverse perspectives and voices to our readers, and the only way to have meaningful diversity at work is to foster an inclusive environment. Diversity for us includes, but is not limited to, gender, ethnicity, race, culture, socio-economic background, religion, age, physical ability, veteran status, country of origin, primary language, sexuality, political preference, education, and family makeup.</p><h3>The Data</h3><p>Every year, we send an optional survey to our staff to gather demographic information and give employees a chance to voice whether they feel our workplace is diverse and inclusive. We sent the survey to staff hired up until November 13, 2018 and the responses are valid as of November 30, 2018. A few notes on the data:</p><ul><li>The survey is anonymous and optional for all employees. Contractors were not included in this survey. In order to capture some of the subgroups of the survey, we cross-referenced survey data with our internal HR data.</li><li>We separate our statistics into tech — which includes engineering, product, and data science — and non-tech, which includes (but is not limited to) marketing, content, operations, human resources, and design. We do not separate the demographics for other functional groups because their small size precludes anonymity.</li><li>Senior employees are defined as individuals who are in one of the top three levels of our six-tier internal leveling system.</li></ul><h3>Who We Are</h3><p>As of November 13, 2018, we are comprised of 98 employees that identify mostly as introverts and ambiverts. We enjoy both outdoor and indoor activities, with a slight preference for staying indoors. Our current employees are based all over the US, with 75% of the company in San Francisco, 15% in New York and the rest working remotely. The largest team is engineering (46% of Medium) followed by Editorial (13%) and Product (11%).</p><h3>Gender</h3><p>The overall gender split for Medium is 39.6% (-0.6 percentage points from 2017) female and 60.4% male. For the tech roles, the split is 31.5% (-6.5pp from 2017) female and 68.5% male, while for non-tech roles, the ratio of female and male employees is even at 50% (+14pp for female held positions from 2017). In senior positions, we have 27.5% (+4.7pp from 2017) of the positions filled by female employees and the remaining 72.5% filled by male employees.</p><figure><img alt=\"\" src=\"https://cdn-images-1.medium.com/max/1024/0*IfWNVVOnUcitMyHO\" /></figure><figure><img alt=\"\" src=\"https://cdn-images-1.medium.com/max/1024/0*mRTGeQSDBjwNpeWD\" /></figure><h3>Race &amp; Ethnicity</h3><p>The current makeup of Medium is 63% of employees that identify as White. That’s an increase of +5pp from the previous year. There are also 24% of employees identifying as Asian, which represents an increase of +2pp from 2017. We have 9% of employees that identify as Black or African American and that’s a decrease of -2pp from last year. Other groups saw a marginal increase of +1–2pp from 2017.</p><p>We do not have any Black, African American, Hispanic, or Latinx employees at the senior level.</p><figure><img alt=\"\" src=\"https://cdn-images-1.medium.com/max/1024/0*AgFQ6X8nwHSOSWFK\" /></figure><h3>Age, LGBTQ+ &amp; Origin</h3><p>There are other areas of diversity that we measure:</p><ul><li>Most of our employees are between 26–30 years old, but there was a decrease of -8pp from the previous year. The company is trending older and now more than 50% of the employees are 31 years and older.</li><li>14% of our employees identify as LGBTQ+, a jump of +4.3pp from 2017.</li><li>Most Medians were born in America but there’s a significant number (45%) of employees that are either immigrants or born of parents that are immigrants.</li></ul><figure><img alt=\"\" src=\"https://cdn-images-1.medium.com/max/1024/0*MltblTnZpD6E4tOQ\" /></figure><figure><img alt=\"\" src=\"https://cdn-images-1.medium.com/max/1024/0*pi6trHyBDkhxCFqb\" /></figure><figure><img alt=\"\" src=\"https://cdn-images-1.medium.com/max/1024/0*wK5HLnzn_WqBlg59\" /></figure><h3>Inclusion</h3><p>We asked employees who they felt should be better represented at Medium. Combining direct answers to this question with free-form comments, 61% of respondents expressed a desire for a more diverse leadership team. Other areas where people felt Medium lacks diverse representation include: race &amp; ethnicity, age, and political views.</p><figure><img alt=\"\" src=\"https://cdn-images-1.medium.com/max/1024/0*SytbY7TWSIWk59Uk\" /></figure><p>The free form comments also capture that as we continue to grow and become increasingly distributed as a workforce, we have an opportunity to ensure better parity around benefits and social events between remote worker and workers in our San Francisco office.</p><img src=\"https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=503dd91c2edd\" width=\"1\" height=\"1\" alt=\"\"><hr><p><a href=\"https://medium.com/blog/medium-the-diversity-report-503dd91c2edd\">Medium: The Diversity Report</a> was originally published in <a href=\"https://medium.com/blog\">The Medium Blog</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>"},{"guid":"https://medium.com/p/aeee8ef5dacf","link":"https://medium.com/blog/ad-free-medium-aeee8ef5dacf?source=rss-504c7870fdb6------2","title":"Ad-Free Medium","author":"Medium","excerpt":"We’ve been putting our energy at Medium into improving quality — hosting more thoughtful and carefully written content, and improving the reading experience. We want to eliminate distractions that get in the way of reading flow and reduce distortions that could undermine your trust in what you read ","updated":"2018-07-17T18:37:47.385Z","published":"Tue, 17 Jul 2018 18:37:47 GMT","categories":["medium","policy"],"content_html":"<p>We’ve been putting our <a href=\"https://blog.medium.com/the-medium-model-3ec28c6f603a\">energy at Medium</a> into improving quality — hosting more thoughtful and carefully written content, and improving the reading experience. We want to eliminate distractions that get in the way of reading flow and reduce distortions that could undermine your trust in what you read on Medium.</p><p>To that end, we‘re adjusting our policies related to commercial content.</p><h3>Ads, Promotions, and Marketing</h3><p>First, we’ll be restricting some kinds of commercial activity that have been allowed in the past, such as sponsorships and links that are mainly promotional. Medium’s business has been ad-free for more than a year now. But some “ad-like” remnants that had value in the past are now less aligned with Medium’s model of using subscriptions and a metered paywall to provide the best quality user experience. This means eliminating certain features that are superficially free, but for which you pay with attention.</p><p>So, as of September 1, 2018, our policies will include:</p><ul><li><strong>First-party promotion is allowed.</strong> You can promote your own work or goods and services you provide, like a link to your website or your book. For posts or publications run by a company (like company blogs), you can promote goods or services provided by your company.</li><li><strong>Third-party advertising and sponsorships are not allowed. </strong>You may not advertise or promote third-party products, services, or brands through Medium posts, publications, or letters. This includes images that indicate brand sponsorship in a post or letter, or as part of a publication name or logo.</li><li><strong>Images functioning as third-party ads are not allowed.</strong> Inline images or embeds that link out and function as banner ads for third-party brands will no longer be allowed.</li><li><strong>You must disclose affiliate links or payment for a post. </strong>Affiliate links, such as link out to Amazon with your code, or any other link out where you will receive a commission or other value, are allowed in posts. But, you must disclose somewhere in the post that it includes affiliate links. If you have received payment, goods or services, or something else of value in exchange for writing a post, you must still disclose this fact in writing within your post (as <a href=\"https://www.ftc.gov/tips-advice/business-center/guidance/ftcs-endorsement-guides-what-people-are-asking\">FTC Rules and Guides</a>, and <a href=\"https://medium.com/policy/medium-rules-30e5502c4eb4\">Medium Rules</a> require).</li></ul><h3>Embedded Content</h3><p>Second, in preparing to comply with GDPR (the European Union’s new General Data Protection Regulation), it led us to step back, take a fresh look at our privacy practices, and renew our efforts to make Medium trustworthy. It raised questions about what types of data collection we should and should not allow through Medium. And in other cases, it led us to think about how to channel third-party data collection on Medium to make sure our users understand as clearly as possible what information about them is captured, by whom, where it winds up, and how it might be used.</p><p>As of September 1, 2018:</p><ul><li>Embeds that directly collect data through form fields will no longer be allowed.</li></ul><p>This includes embeds that facilitate the submission of email addresses and other personally identifying information through forms (such as Upscribe or Rabbut) and the submission of credit card information (such as Gumroad). We understand that this might make life harder for writers and publications who want to collect information directly from users. But, we believe this change is necessary to ensure that Medium readers know where their data is going and how it will be used.</p><p>Going forward, if you want to collect information from your users, you will need to link out from your post on Medium to a form hosted elsewhere that makes it clear to a user that they are no longer in the Medium network. We are working with Upscribe, Rabbut, and Gumroad so that their services function in line with these Medium policies.</p><p>We will continue to allow embeds that display content, such as YouTube, Vimeo, Soundcloud, GitHub, and others, as explained in our <a href=\"https://help.medium.com/hc/en-us/articles/214981378-Embeds\">Help Center</a>. Our <a href=\"https://medium.com/policy/medium-privacy-policy-f03bf92035c9\">Privacy Policy</a> discusses in more detail how we treat this type of embed.</p><p>Thank you. We’re grateful for your continued use of Medium and appreciate your working with us to make Medium a place for thoughtful, high-quality stories.</p><img src=\"https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=aeee8ef5dacf\" width=\"1\" height=\"1\" alt=\"\"><hr><p><a href=\"https://medium.com/blog/ad-free-medium-aeee8ef5dacf\">Ad-Free Medium</a> was originally published in <a href=\"https://medium.com/blog\">The Medium Blog</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>"}]},"meta":{"timestamp":"2026-06-02T16:53:18.677Z","request_id":"4a4bca42-587d-4120-837e-7ab6f87a6765"},"status":"ok","message":"User posts","success":true}}}},"401":{"description":"Missing or invalid x-oanor-key header"},"402":{"description":"Active subscription required"},"429":{"description":"Rate-limit or monthly quota reached"},"502":{"description":"Upstream did not respond"}}}},"/v1/meta":{"get":{"operationId":"get_v1_meta","tags":["Meta"],"summary":"Spec","description":"","parameters":[],"security":[{"oanorKey":[]}],"responses":{"200":{"description":"OK","content":{"application/json":{"example":{"data":{"auth":"none upstream; gateway requires x-api-key","name":"Medium API","note":"Live, no cache. Returns recent posts (RSS-limited, typically up to 10) with title, author, link, categories and full content HTML. user = @handle, tag = topic slug, publication = publication slug.","source":"Medium public RSS feeds (medium.com/feed/...)","endpoints":4},"meta":{"timestamp":"2026-06-02T16:53:18.818Z","request_id":"0730090c-9cd6-48bf-9e55-c174374c75db"},"status":"ok","message":"Meta","success":true}}}},"401":{"description":"Missing or invalid x-oanor-key header"},"402":{"description":"Active subscription required"},"429":{"description":"Rate-limit or monthly quota reached"},"502":{"description":"Upstream did not respond"}}}}},"x-oanor-pricing":[{"slug":"free","name":"Free","price_cents_month":0,"monthly_call_quota":3500,"rps_limit":2,"hard_limit":true},{"slug":"starter","name":"Starter","price_cents_month":680,"monthly_call_quota":67000,"rps_limit":8,"hard_limit":true},{"slug":"pro","name":"Pro","price_cents_month":1950,"monthly_call_quota":335000,"rps_limit":20,"hard_limit":true},{"slug":"mega","name":"Mega","price_cents_month":4650,"monthly_call_quota":1640000,"rps_limit":50,"hard_limit":true}],"x-oanor-marketplace-url":"https://www.oanor.com/api/medium-api"}