<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/"
    xmlns:atom="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/" version="2.0">
    <channel>
        
        <title>
            <![CDATA[ Adejumo Ridwan Suleiman - freeCodeCamp.org ]]>
        </title>
        <description>
            <![CDATA[ Browse thousands of programming tutorials written by experts. Learn Web Development, Data Science, DevOps, Security, and get developer career advice. ]]>
        </description>
        <link>https://www.freecodecamp.org/news/</link>
        <image>
            <url>https://cdn.freecodecamp.org/universal/favicons/favicon.png</url>
            <title>
                <![CDATA[ Adejumo Ridwan Suleiman - freeCodeCamp.org ]]>
            </title>
            <link>https://www.freecodecamp.org/news/</link>
        </image>
        <generator>Eleventy</generator>
        <lastBuildDate>Wed, 20 May 2026 15:58:44 +0000</lastBuildDate>
        <atom:link href="https://www.freecodecamp.org/news/author/adejumo/rss.xml" rel="self" type="application/rss+xml" />
        <ttl>60</ttl>
        
            <item>
                <title>
                    <![CDATA[ How to Forecast Time Series Data with Python Darts ]]>
                </title>
                <description>
                    <![CDATA[ When analyzing time series data, your main objective is to consider the period during which the data is collected and how your variable of interest changes over time. There are various libraries for time series forecasting in Python, and Darts is one... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-forecast-time-series-data-with-python-darts/</link>
                <guid isPermaLink="false">68e40c4dd441014d7e52dc0d</guid>
                
                    <category>
                        <![CDATA[ data visualization ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Data Science ]]>
                    </category>
                
                    <category>
                        <![CDATA[ data analysis ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Machine Learning ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Python ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Adejumo Ridwan Suleiman ]]>
                </dc:creator>
                <pubDate>Mon, 06 Oct 2025 18:37:01 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1759775700643/6f7d18b3-2060-4708-b56e-3450acf58546.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>When analyzing time series data, your main objective is to consider the period during which the data is collected and how your variable of interest changes over time.</p>
<p>There are various libraries for time series forecasting in Python, and <a target="_blank" href="https://unit8co.github.io/darts/">Darts</a> is one of them. Unlike other forecasting libraries, Darts is a high-level forecasting library with algorithms to handle various time series data, regardless of the kind of trend they portray.</p>
<p>This tutorial will walk you through how you can forecast time series data using Python Darts. This will help you make meaningful insights whenever you come across time series data such as stock prices, weather measurements, and so on.</p>
<h3 id="heading-heres-what-well-cover">Here’s what we’ll cover:</h3>
<ul>
<li><p><a class="post-section-overview" href="#heading-what-is-python-darts">What is Python Darts?</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-prerequisites">Prerequisites</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-set-up-dependencies">How to Set Up Dependencies</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-understanding-the-dataset">Understanding the Dataset</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-prepare-the-data-for-darts">How to Prepare the Data for Darts</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-build-a-forecasting-model">How to Build a Forecasting Model</a></p>
<ul>
<li><p><a class="post-section-overview" href="#heading-classical-model">Classical Model</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-machine-learning-models">Machine Learning Models</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-forecast-with-deep-learning-models">How to Forecast with Deep Learning models</a></p>
</li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-model-evaluation">Model Evaluation</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-backtesting">BackTesting</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-hyper-parameter-tuning">Hyper Parameter Tuning</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-real-world-use-cases">Real-World Use Cases</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-best-practices">Best Practices</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-conclusion">Conclusion</a></p>
</li>
</ul>
<h2 id="heading-what-is-python-darts">What is Python Darts?</h2>
<p>Python Darts is an open-source library for time series analysis and forecasting. It has various models ranging from statistical time series models like ARIMA, and SARIMA, to machine learning and deep learning models like Prophet, and LSTM.</p>
<p>It has various algorithms for handling missing imputations in time series data, and can handle time series problems ranging from univariate, multivariate to hierarchical time series.</p>
<h2 id="heading-prerequisites">Prerequisites</h2>
<p>Before we proceed, you will need to have the following:</p>
<ul>
<li><p>Python 3.9+ installed.</p>
</li>
<li><p>Jupyter Notebook, Google Colab, or Positron to run your code.</p>
</li>
<li><p>Download the <a target="_blank" href="https://www.kaggle.com/datasets/kalilurrahman/netflix-stock-data-live-and-latest">Netflix stock data</a>.</p>
</li>
<li><p>Have the following libraries installed:</p>
<ul>
<li><p><code>darts</code> for time series analysis</p>
</li>
<li><p><code>pandas</code> for data wrangling</p>
</li>
<li><p><code>matplotlib</code> for data visualization.</p>
</li>
</ul>
</li>
</ul>
<h2 id="heading-how-to-set-up-dependencies">How to Set Up Dependencies</h2>
<p>Load the following libraries.</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> matplotlib.pyplot <span class="hljs-keyword">as</span> plt
<span class="hljs-keyword">import</span> pandas <span class="hljs-keyword">as</span> pd
<span class="hljs-keyword">import</span> darts
<span class="hljs-keyword">from</span> darts <span class="hljs-keyword">import</span> TimeSeries
<span class="hljs-keyword">from</span> darts.models <span class="hljs-keyword">import</span> ARIMA
<span class="hljs-keyword">from</span> darts.models <span class="hljs-keyword">import</span> RegressionModel
<span class="hljs-keyword">from</span> lightgbm <span class="hljs-keyword">import</span> LGBMRegressor
<span class="hljs-keyword">from</span> darts.models <span class="hljs-keyword">import</span> RNNModel
<span class="hljs-keyword">from</span> darts.metrics <span class="hljs-keyword">import</span> mape
<span class="hljs-keyword">import</span> itertools
</code></pre>
<h2 id="heading-understanding-the-dataset">Understanding the Dataset</h2>
<p>The Netflix stock data contains historical daily prices of Netflix stock from the year 2002 till date.</p>
<p>Load the data and have a preview of it.</p>
<pre><code class="lang-python">netflix = pd.read_csv(<span class="hljs-string">"/kaggle/input/netflix-stock-data-live-and-latest/Netflix_stock_history.csv"</span>)
netflix[<span class="hljs-string">'Date'</span>] = pd.to_datetime(netflix[<span class="hljs-string">'Date'</span>], utc=<span class="hljs-literal">True</span>).dt.tz_convert(<span class="hljs-literal">None</span>)
netflix.head()
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1757927775470/2d4b542c-3869-40c5-844c-a733b5cc4bea.png" alt="Image showing the first 5 rows of the Netflix stock data" class="image--center mx-auto" width="1059" height="484" loading="lazy"></p>
<p>To forecast a time series data, we need a <code>Date</code> column, which we already have, and then the variable of interest. We have several variables, but for this tutorial, we will focus on the <code>Close</code> variable of Netflix stocks.</p>
<p>Let’s visualize the data to see how Netflix closing price performed over the years.</p>
<pre><code class="lang-python">netflix.plot(x=<span class="hljs-string">'Date'</span>, y=<span class="hljs-string">'Close'</span>, figsize=(<span class="hljs-number">10</span>,<span class="hljs-number">5</span>))
plt.show()
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1757928810807/75a1fa13-4f2e-4bdd-a539-5eaf2663843a.png" alt="Image showing a line chart of Netflix stock data from 2000 to date" class="image--center mx-auto" width="1036" height="517" loading="lazy"></p>
<p>From the chart above, you can see that Netflix stock showed exponential growth in recent years. This means that the data is non-stationary, implying that there are no consistent changes over time.</p>
<p>There are a lot of random fluctuations in the data, which might make it difficult to forecast. Such data usually requires advanced models to handle the various fluctuations or noise present in the data.</p>
<h2 id="heading-how-to-prepare-the-data-for-darts"><strong>How to Prepare the Data for Darts</strong></h2>
<p>Before preparing the data for Darts, you need to take note of few things.</p>
<p>First of all, if you look at our data preview earlier on, you would notice that it is recorded daily, we also need to fill in missing dates.</p>
<p>Copy and paste this code into your notebook.</p>
<pre><code class="lang-python">start = netflix[<span class="hljs-string">'Date'</span>].min()
end = netflix[<span class="hljs-string">'Date'</span>].max()

netflix = (
    netflix.set_index(<span class="hljs-string">'Date'</span>)
           .reindex(pd.date_range(start=start, end=end, freq=<span class="hljs-string">'D'</span>))
           .ffill()
           .reset_index()
           .rename(columns={<span class="hljs-string">'index'</span>: <span class="hljs-string">'Date'</span>})
)
netflix.head()
</code></pre>
<p>The code above ensures the <code>netflix</code> dataset has a continuous daily time series by filling in missing dates.</p>
<p>First, it finds the earliest <code>start</code> and latest <code>end</code> dates in the data, then creates a full daily date range between them.</p>
<p>By setting the <code>Date</code> column as the index and using <code>.reindex()</code> method, it inserts rows for any missing dates, which initially contain <code>NaN</code>.</p>
<p>The <code>.ffill()</code> method (forward fill) replaces these gaps by carrying forward the last known value, which is common for stock data when markets are closed, such as weekends.</p>
<p>Finally, the index is reset, and the column is renamed back to <code>Date</code>, producing a clean, continuous dataset ready for time series analysis.</p>
<p>Next, we need to convert the data to a Darts <code>Timeseries</code> object to make it usable by the Darts library.</p>
<pre><code class="lang-python"> = TimeSeries.from_dataframe(
    netflix,
    time_col=<span class="hljs-string">'Date'</span>,
    value_cols=<span class="hljs-string">'Close'</span>,
)
</code></pre>
<p>The code above converts the <code>netflix</code> DataFrame into a Darts <code>TimeSeries</code> object, which is optimized for time series modeling and forecasting.</p>
<p>It takes the <code>Date</code> column (<code>time_col='Date'</code>) as the timeline and the <code>Close</code> column (<code>value_cols='Close'</code>) as the target values to forecast.</p>
<p>The resulting <code>series</code> object is now structured for use with Darts’ advanced forecasting models like ARIMA, Prophet, RNNs, and other time series algorithms.</p>
<p>Just like you would with any other machine learning model, you need to split your data into a training set and a validation set.</p>
<pre><code class="lang-python">train, val = series.split_before(<span class="hljs-number">0.8</span>)
</code></pre>
<h2 id="heading-how-to-build-a-forecasting-model"><strong>How to Build a Forecasting Model</strong></h2>
<p>When building a forecasting model, you have the privilege of trying various models and picking the best-performing one.</p>
<p>The Darts library has various algorithms for time series analysis, from popular statistical algorithms like the Auto Regressive Integrated Moving Average (ARIMA) and Moving Average (MA) models, to machine learning and deep learning algorithms like Prophet and Long Short Term Memory (LSTM).</p>
<p>Note, I will only demonstrate how these algorithms work - it’s not necessary that we get accurate model metrics. But with further feature engineering, hyperparameter tuning, and cross-validation, you can get good results on your own.</p>
<h3 id="heading-classical-model">Classical Model</h3>
<p>The classical mode is the use of statistical time series models such as ARIMA. ARIMA is made up of the following components:</p>
<ul>
<li><p><strong>AR (AutoRegressive):</strong> Predict past values by looking at previous ones.</p>
</li>
<li><p><strong>I (Integrated):</strong> Remove trends by focusing on changes instead of raw values.</p>
</li>
<li><p><strong>MA (Moving Average):</strong> Learn from the errors of past predictions to improve accuracy.</p>
</li>
</ul>
<p>Run the code below in your notebook to fit an ARIMA model.</p>
<pre><code class="lang-python">arima_model = ARIMA()
arima_model.fit(train)
arima_forecast = arima_model.predict(len(val))
</code></pre>
<p>To visualize the forecast by the model, call the <code>.plot()</code> method on the <code>forecast</code> object.</p>
<pre><code class="lang-python">series.plot(label=<span class="hljs-string">'actual'</span>)
arima_forecast.plot(label=<span class="hljs-string">'forecast'</span>)
plt.legend()
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1758028284156/a40f2341-cfc6-4a9f-8297-e0511c2bb254.png" alt="Image showing the ARIMA model forecast of netflix stock " class="image--center mx-auto" width="820" height="646" loading="lazy"></p>
<p>You can improve the model by adding some additional parameters to the <code>ARIMA()</code> class. You can read more about that in the <a target="_blank" href="https://unit8co.github.io/darts/generated_api/darts.models.forecasting.arima.html">Darts documentation</a>.</p>
<h3 id="heading-machine-learning-models"><strong>Machine Learning Models</strong></h3>
<p>Classical models like ARIMA can’t handle non-linear data. Machine learning models fill this gap. We’ll use the LightGBM model as an example.</p>
<p>The LightGBM is a machine learning model that builds models sequentially based on decision trees. It adds new decision trees that correct the errors of previous trees.</p>
<p>Although it was not designed to handle time series, with some feature engineering such as lags, rolling statistics, and seasonal indicators, you can make it learn patterns from time series data.</p>
<p>Run this code on your notebook to fit a LightGBM model on the Netflix data.</p>
<pre><code class="lang-python">lgbm = LGBMRegressor()
lgbm_model = RegressionModel(lags=<span class="hljs-number">12</span>, model=lgbm)
lgbm_model.fit(train)
lgbm_forecast = lgbm_model.predict(len(val))
</code></pre>
<p>From the code above, the <code>lag</code> argument is set to <code>12</code>, which is the value of the Netflix stock price for 12 days before a selected day.</p>
<p>Let’s have a view of the forecast by running the following code.</p>
<pre><code class="lang-python">series.plot(label=<span class="hljs-string">'actual'</span>)
lgbm_forecast.plot(label=<span class="hljs-string">'forecast'</span>)
plt.legend()
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1758029933172/54f34a69-4f6b-4b44-85ab-d0b45931d701.png" alt="Image showing the LightGBM model forecast of netflix stock " class="image--center mx-auto" width="813" height="631" loading="lazy"></p>
<p>You can read more about tuning the LightGBM model from the <a target="_blank" href="https://unit8co.github.io/darts/generated_api/darts.models.forecasting.lgbm.html">Darts documentation</a> to improve the above model.</p>
<h3 id="heading-how-to-forecast-with-deep-learning-models"><strong>How to Forecast with Deep Learning models</strong></h3>
<p>You can go for deep learning models designed for time series, such as LSTM, a kind of Recurrent Neural Network (RNN) designed to capture long-term dependencies in sequential data.</p>
<p>Run the following code to build the LSTM model.</p>
<pre><code class="lang-python">lstm_model = RNNModel(model=<span class="hljs-string">'LSTM'</span>, input_chunk_length=<span class="hljs-number">12</span>, output_chunk_length=<span class="hljs-number">6</span>, n_epochs=<span class="hljs-number">100</span>)
lstm_model.fit(train)
lstm_forecast = rnn_model.predict(len(val))
</code></pre>
<p>Now let’s visualize the forecast and see what we have.</p>
<pre><code class="lang-python">series.plot(label=<span class="hljs-string">'actual'</span>)
lstm_forecast.plot(label=<span class="hljs-string">'forecast'</span>)
plt.legend()
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1758116174578/2ff80218-2254-452d-8d4c-2f85c61612de.png" alt="Image showing the LSTM model forecast of Netflix stock " class="image--center mx-auto" width="682" height="526" loading="lazy"></p>
<p>You can look up the <a target="_blank" href="https://unit8co.github.io/darts/generated_api/darts.models.forecasting.rnn_model.html">Darts documentation</a> to improve the model and check out other deep learning models also.</p>
<h2 id="heading-model-evaluation"><strong>Model Evaluation</strong></h2>
<p>Now that you have three models, you need to select the best one among them using the Mean Absolute Percentage Error (MAPE).</p>
<p>It expresses the average absolute error as a percentage of the actual values, and the closer your value is to 0, the better your model.</p>
<p>Run the following to print the MAPE of each respective model.</p>
<pre><code class="lang-python">arima_error = mape(val, arima_forecast)
print(<span class="hljs-string">"MAPE:"</span>, arima_error)
lgbm_error = mape(val, lgbm_forecast)
print(<span class="hljs-string">"MAPE:"</span>, lgbm_error)
lstm_error = mape(val, lstm_forecast)
print(<span class="hljs-string">"MAPE:"</span>, lstm_error)
</code></pre>
<pre><code class="lang-bash">&gt; MAPE: 38.33262525601514
&gt; MAPE: 39.00241495209449
&gt; MAPE: 38.82910057097827
</code></pre>
<p>The model with the lowest MAPE is the ARIMA model with approximately 38.33, which means it’s our best-performing model.</p>
<h2 id="heading-backtesting">BackTesting</h2>
<p>Darts has a feature called backtesting that allows you to evaluate your models based on historical data, using a rolling forecast.</p>
<p>Backtesting is like a time machine for forecasting. It simulates how your model would have performed in the past by repeatedly training it on historical data up to a certain point, making a prediction for the next step, then moving forward, and repeating the process.</p>
<p>This rolling evaluation simulates how the model would behave in real-world conditions, where future data is unknown, helping you measure its consistency and reliability over time, instead of just testing it once on a single validation set.</p>
<p>Since the ARIMA model is currently our best-performing model, run the code below to implement backtesting.</p>
<pre><code class="lang-python">
<span class="hljs-comment"># Perform backtesting on the training + validation series</span>
backtest_series = train.concatenate(val)

<span class="hljs-comment"># Backtest</span>
backtest_forecast = arima_model.historical_forecasts(
    series=backtest_series,
    start=<span class="hljs-number">0.8</span>,          <span class="hljs-comment"># fraction of the series to start forecasting from</span>
    forecast_horizon=len(val),
    stride=<span class="hljs-number">1</span>,           <span class="hljs-comment"># step size of rolling forecast</span>
    retrain=<span class="hljs-literal">True</span>,       <span class="hljs-comment"># retrain the model at each step</span>
    verbose=<span class="hljs-literal">True</span>
)

<span class="hljs-comment"># Compute metrics</span>
error = mape(backtest_series[-len(val):], backtest_forecast)
print(<span class="hljs-string">f"MAPE: <span class="hljs-subst">{error:<span class="hljs-number">.2</span>f}</span>%"</span>)
</code></pre>
<pre><code class="lang-bash">&gt; historical forecasts: 100%|██████████| 1/1 [00:02&lt;00:00,  2.69s/it]MAPE: 47.27%
</code></pre>
<p>In the code above,</p>
<ul>
<li><p>The <code>start</code> argument defines where to start backtesting, which in this case is the last 20% series of the data.</p>
</li>
<li><p>The <code>forecast_horizon</code> is how many steps ahead to forecast at each point.</p>
</li>
<li><p>The <code>stride</code> is how frequently to retrain/forecast.</p>
</li>
<li><p>The <code>retrain=True</code> refits the model at each step for realistic evaluation.</p>
</li>
</ul>
<p>You can see that the MAPE, after backtesting, is higher because backtesting is more realistic, and it is more difficult to achieve a lower MAPE.</p>
<p>On your own, you can try to replicate backtesting for the other models.</p>
<h2 id="heading-hyper-parameter-tuning">Hyper Parameter Tuning</h2>
<p>The ARIMA model has three hyperparameter:</p>
<ul>
<li><p><code>p</code> which is the AR order</p>
</li>
<li><p><code>d</code> which is the differencing order</p>
</li>
<li><p><code>q</code> which is the MA order</p>
</li>
</ul>
<p>You can use either grid or random search to tune your ARIMA model in Darts.</p>
<pre><code class="lang-python"><span class="hljs-comment"># Define possible values</span>
p_values = range(<span class="hljs-number">0</span>, <span class="hljs-number">4</span>)
d_values = range(<span class="hljs-number">0</span>, <span class="hljs-number">3</span>)
q_values = range(<span class="hljs-number">0</span>, <span class="hljs-number">4</span>)

best_mape = float(<span class="hljs-string">'inf'</span>)
best_params = <span class="hljs-literal">None</span>

<span class="hljs-keyword">for</span> p, d, q <span class="hljs-keyword">in</span> itertools.product(p_values, d_values, q_values):
    <span class="hljs-keyword">try</span>:
        arima_model = ARIMA(p=p, d=d, q=q)
        arima_model.fit(train)
        arima_forecast = arima_model.predict(len(val))
        arima_error = mape(val, arima_forecast)
        <span class="hljs-keyword">if</span> arima_error &lt; best_mape:
            best_mape = arima_error
            best_params = (p, d, q)
    <span class="hljs-keyword">except</span> Exception <span class="hljs-keyword">as</span> e:
        <span class="hljs-comment"># Some combinations may fail</span>
        <span class="hljs-keyword">continue</span>

print(<span class="hljs-string">f"Best ARIMA params: p=<span class="hljs-subst">{best_params[<span class="hljs-number">0</span>]}</span>, d=<span class="hljs-subst">{best_params[<span class="hljs-number">1</span>]}</span>, q=<span class="hljs-subst">{best_params[<span class="hljs-number">2</span>]}</span> with MAPE=<span class="hljs-subst">{best_mape:<span class="hljs-number">.2</span>f}</span>%"</span>)
</code></pre>
<pre><code class="lang-bash">&gt; Best ARIMA params: p=2, d=0, q=3 with MAPE=35.95%
</code></pre>
<p>In the above code, you define a range of possible values for the <code>p</code>, <code>d</code> , and <code>q</code> components, iterating over each combination of those values and choosing the model with the best MAPE among them.</p>
<p>Note that each model has its specific parameter you would have to tune, and you will need to check <a target="_blank" href="https://unit8co.github.io/darts/userguide/hyperparameter_optimization.html">the Darts documentation</a> for the hyperparameters of other models.</p>
<h2 id="heading-real-world-use-cases"><strong>Real-World Use Cases</strong></h2>
<p>Forecasting time series data has a lot of real-world applications, some of which are:</p>
<ul>
<li><p><strong>Stock price prediction:</strong> Like the dataset used in this tutorial, forecasting is used in finance for stock price prediction, allowing investors to manage risk.</p>
</li>
<li><p><strong>Demand forecasting for inventory:</strong> As a store owner, you can forecast product demands based on past sales of a product. This lets you know products that are in high demand.</p>
</li>
<li><p><strong>Energy consumption prediction:</strong> Governments, industries, and consumers can plan and manage energy production, distribution, and consumption efficiently, based on data from past usage. This helps to avoid blackouts and wastage, enabling them to prepare ahead.</p>
</li>
</ul>
<h2 id="heading-best-practices">Best Practices</h2>
<ul>
<li><p><strong>Always visualize residuals:</strong> Residuals are the difference between forecasted values and actual values. You must visualize them to detect outliers and unusual events.</p>
</li>
<li><p><strong>Perform proper backtesting:</strong> Backtesting lets you see a more realistic model, subjected to various changes that can occur in real life. When you backtest all your models, you end up getting a model that performs well when forecasting.</p>
</li>
<li><p><strong>Avoid data leakage:</strong> Do not train your models on validation sets to avoid bias, and always use cross-validation where necessary.</p>
</li>
<li><p><strong>Use domain knowledge for feature engineering:</strong> Ensure you understand the data you are working with. This comes in handy in feature engineering, when you want to come up with new features to help your forecasting model, especially in multivariate time series forecasting.</p>
</li>
</ul>
<h2 id="heading-conclusion"><strong>Conclusion</strong></h2>
<p>This tutorial is more like an overview, especially if you are new to time series, but you can build a lot just from what you have learned.</p>
<p>You already have an idea of what time series and forecasting are, and how you can use the Darts Python library to achieve that.</p>
<p>You also learned of various models for forecasting time series data, and how you can apply techniques such as backtesting and hyperparameter tuning to achieve better results.</p>
<p>Another interesting thing with Darts is its ability to handle <a target="_blank" href="https://unit8co.github.io/darts/userguide/timeseries.html#hierarchical-time-series">hierarchical time series</a>. Here, data is structured at aggregated levels.</p>
<p>Darts is one of the most powerful time series libraries in Python and has a lot of models to handle various cases. You can proceed to explore models such as <a target="_blank" href="https://unit8co.github.io/darts/generated_api/darts.models.forecasting.transformer_model.html">Transformers</a> and also <a target="_blank" href="https://unit8co.github.io/darts/examples/01-multi-time-series-and-covariates.html">multi-series forecasting</a>, which are used for special use cases.</p>
<p>If you are interested in more data science and statistics articles, don’t forget to check out <a target="_blank" href="https://learndata.xyz/blog">my blog</a>.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Extract  YouTube Analytics Data and Analyze in Python ]]>
                </title>
                <description>
                    <![CDATA[ If you’re a YouTube content creator, you’ll make data-driven decisions when posting content. This helps you target the right audience when creating your videos. YouTube Studio provides YouTube Analytics, where you can get comprehensive data about you... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/extract-youtube-analytics-data-and-analyze-in-python/</link>
                <guid isPermaLink="false">67e425c92a171465d4fb4cce</guid>
                
                    <category>
                        <![CDATA[ Python ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Machine Learning ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Data Science ]]>
                    </category>
                
                    <category>
                        <![CDATA[ youtube ]]>
                    </category>
                
                    <category>
                        <![CDATA[ data analysis ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Adejumo Ridwan Suleiman ]]>
                </dc:creator>
                <pubDate>Wed, 26 Mar 2025 16:05:29 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1743005089726/39e2323d-8f7b-4bf4-94cb-288aeb9cea4f.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>If you’re a YouTube content creator, you’ll make data-driven decisions when posting content. This helps you target the right audience when creating your videos.</p>
<p>YouTube Studio provides YouTube Analytics, where you can get comprehensive data about your channel. But there is a caveat: most of the statistics provided by YouTube Analytics are descriptive and not predictive. This means information like future views, subscriber counts, and factors influencing watch time or earnings are unavailable. This means you’ll need to calculate these metrics yourself.</p>
<p>In this article, you’ll learn how to export data from YouTube Analytics to Python so you can analyze it further or create visualizations. You can even build your own custom dashboard using various Python libraries like <a target="_blank" href="https://streamlit.io/">Streamlit</a>, <a target="_blank" href="https://shiny.posit.co/py/">Shiny</a>, or <a target="_blank" href="https://dash.plotly.com/">Dash</a>.</p>
<h3 id="heading-heres-what-we">Here’s what we</h3>
<ul>
<li><p><a class="post-section-overview" href="#heading-prerequisites">Prerequisites</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-step-1-identify-the-problem-statement">Step 1: Identify the Problem Statement</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-step-2-extract-the-data">Step 2: Extract the Data</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-step-3-analyze-the-data-in-python">Step 3: Analyze the Data in Python</a></p>
<ul>
<li><p><a class="post-section-overview" href="#heading-correlation-analysis">Correlation Analysis</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-audience-retention-analysis">Audience Retention Analysis</a></p>
</li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-conclusion">Conclusion</a></p>
</li>
</ul>
<h2 id="heading-prerequisites">Prerequisites</h2>
<ul>
<li><p>Active YouTube and YouTube Studio Account</p>
</li>
<li><p>Jupyter Notebook, Google Colab, Kaggle, or any other environment that supports Python</p>
</li>
<li><p><a target="_blank" href="https://pandas.pydata.org/">Pandas</a> library installed</p>
</li>
<li><p><a target="_blank" href="https://seaborn.pydata.org/">Seaborn</a> library installed</p>
</li>
<li><p><a target="_blank" href="https://matplotlib.org/">Matplotlib</a> library installed</p>
</li>
</ul>
<h2 id="heading-step-1-identify-the-problem-statement">Step 1: Identify the Problem Statement</h2>
<p>Before proceeding, we need to know what we’re looking for – because YouTube Analytics has many metrics, and this can get overwhelming. My channel doesn’t have a ton of subscribers, but I have quite a few videos and views. So we’ll use my data as an example.</p>
<p>Just note that this analysis I’ll conduct in this tutorial is specific to my channel and can vary from channel to channel. You’ll be able to use the techniques here to answer the same/similar questions using your data, but your results will be different from mine.</p>
<p>Here are the questions I would like to find an answer for:</p>
<ol>
<li><strong>Correlation Analysis</strong></li>
</ol>
<ul>
<li><p><strong>Views and watch time</strong> – Are longer watch times associated with higher views?</p>
</li>
<li><p><strong>Views and subscribers</strong> – Do more views translate to more subscribers?</p>
</li>
<li><p><strong>Impressions and Click-Through Rate (CTR%) –</strong> Does a stronger impression lead to better engagement?</p>
</li>
<li><p><strong>Watch time and average view duration</strong> – Are longer videos watched more?</p>
</li>
</ul>
<ol start="2">
<li><strong>Audience Retention Analysis</strong></li>
</ol>
<ul>
<li><p><strong>Average view duration vs. Video length</strong> – Are longer videos watched in full?</p>
</li>
<li><p><strong>Drop-off points</strong> – Which duration range has the best retention?</p>
</li>
<li><p><strong>Retention Rate (%)</strong> – Watch time divided by duration?</p>
</li>
</ul>
<h2 id="heading-step-2-extract-the-data">Step 2: Extract the Data</h2>
<p>Sign in to your YouTube Studio account, go to the Analytics tab, and click Advanced mode.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742548010236/1392de34-a280-4117-9a3d-feda80392f62.png" alt="Image showing YouTube Analytics Dashboard and the Advanced Mode" class="image--center mx-auto" width="1920" height="927" loading="lazy"></p>
<p>This will open a dashboard showing comprehensive descriptive analytics of your YouTube channel. This can get overwhelming, as there are a lot of metrics and filters with various types of data. This is why I emphasized the importance of knowing your problem and identifying your questions before diving in.</p>
<p>You can select the range of data you are interested in using the date dropdown (1 in the image below) and the Compare to button (2) to compare data from different date ranges.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742548329162/3b8be0ea-769a-4723-b427-f911b3cfec83.png" alt="Image showing the date dropdown and the Compare to button" class="image--center mx-auto" width="1914" height="904" loading="lazy"></p>
<p>The column headers you see in the dashboard are the filters. Each contains different metrics, and you can find some metrics in one or more filters. You can play around with the tabs and dropdowns to understand them better.</p>
<p>This is just a foundation for understanding your YouTube channel performance. If you have a long-running channel with a large number of subscribers and views, trust me – you can get a lot of insights from your data.</p>
<p>For this tutorial, I will select my entire lifetime data (1) and click the download button at the top right-hand corner (2).</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742548442210/8fbddcac-98cb-4e52-9355-5383e6afc172.png" alt="Image showing the lifetime option under the date dropdown" class="image--center mx-auto" width="1900" height="915" loading="lazy"></p>
<p>This will display two options: whether to open the data in Google Sheets in a new tab or download the CSV file.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742548490620/c8829a2b-228b-45fd-8789-45dfb397f2da.png" alt="Image showing the download options to open the data in a google sheets new tab or download the csv" class="image--center mx-auto" width="718" height="474" loading="lazy"></p>
<p>Since we want to use the data in Python, select the option to download the CSV file. After downloading the file, extract the files from the zip folder, and inside the extracted folder, you will see three CSV files: <code>Chart data.csv</code>, <code>Table data.csv</code>, and <code>Totals.csv</code>.</p>
<p>For this tutorial, we are interested in the <code>Table data.csv</code>. Click the data to open and view it in Excel to do some manual data cleaning before importing the data in Python.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742548741025/ace69aaf-bb0e-40de-aa1e-e716bb4182aa.png" alt="Image showing the Table data in Excel" class="image--center mx-auto" width="1891" height="604" loading="lazy"></p>
<p>The data is a list of all the videos on my YouTube channel, which is forty (yours might have more or fewer). Remove the first row, which is the <code>Total</code> row, and save the changes.</p>
<p>Here are the columns in the dataset:</p>
<ul>
<li><p><code>Content</code>: The video id</p>
</li>
<li><p><code>Video title</code>: The video title</p>
</li>
<li><p><code>Video publish time</code>: The day the video was published</p>
</li>
<li><p><code>Duration</code>: The video duration in seconds</p>
</li>
<li><p><code>Views</code>: The number of views per video</p>
</li>
<li><p><code>Watch time</code>: The estimated amount of video watch time by your audience in hours</p>
</li>
<li><p><code>Subscribers</code>: Change in total subscribers found by subtracting subscribers lost from subscribers gained for the selected date and region.</p>
</li>
<li><p><code>Average view duration</code>: Estimated average minutes watched per video.</p>
</li>
<li><p><code>Impressions</code>: Number of times your videos were shown to viewers.</p>
</li>
<li><p><code>Impressions click-through rate (%)</code>: Number of times viewers clicked your video after seeing an impression.</p>
</li>
</ul>
<h2 id="heading-step-3-analyze-the-data-in-python">Step 3: Analyze the Data in Python</h2>
<p>Go to your Jupyter Notebook and import the Pandas, Seaborn, and Matplotlib libraries.</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> pandas <span class="hljs-keyword">as</span> pd
<span class="hljs-keyword">import</span> seaborn <span class="hljs-keyword">as</span> sns
<span class="hljs-keyword">import</span> matplotlib.pyplot <span class="hljs-keyword">as</span> plt
</code></pre>
<p>Next, import the <code>Table data.csv</code> file.</p>
<pre><code class="lang-python"><span class="hljs-comment"># Load data</span>
df = pd.read_csv(<span class="hljs-string">"/content/Table data.csv"</span>)
</code></pre>
<h3 id="heading-correlation-analysis">Correlation Analysis</h3>
<p>Concerning our problem statement, we are going to plot a <a target="_blank" href="https://www.quanthub.com/how-to-read-a-correlation-heatmap/">correlation heatmap</a> between the following variables: <code>Views</code>, <code>Watch time (hours)</code>, <code>Subscribers</code>, <code>Average view duration</code>, and <code>Impressions-click-through rate (%)</code> to see the strength and direction of the relationship between them.</p>
<pre><code class="lang-python"><span class="hljs-comment"># Convert "Average view duration" (formatted as H:M:S) to seconds</span>
df[<span class="hljs-string">'Average view duration'</span>] = pd.to_timedelta(df[<span class="hljs-string">'Average view duration'</span>]).dt.total_seconds()

<span class="hljs-comment"># Select relevant columns for correlation analysis</span>
correlation_data = df[[<span class="hljs-string">'Views'</span>, <span class="hljs-string">'Watch time (hours)'</span>, <span class="hljs-string">'Subscribers'</span>, <span class="hljs-string">'Average view duration'</span>, <span class="hljs-string">'Impressions'</span>, <span class="hljs-string">'Impressions click-through rate (%)'</span>]]

<span class="hljs-comment"># Compute correlation matrix</span>
corr_matrix = correlation_data.corr()

<span class="hljs-comment"># Visualization using a heatmap</span>
plt.figure(figsize=(<span class="hljs-number">10</span>, <span class="hljs-number">6</span>))
sns.heatmap(corr_matrix, annot=<span class="hljs-literal">True</span>, cmap=<span class="hljs-string">'coolwarm'</span>, fmt=<span class="hljs-string">".2f"</span>, linewidths=<span class="hljs-number">0.5</span>)
plt.title(<span class="hljs-string">"YouTube Analytics Correlation Heatmap"</span>)
plt.show()
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742632975699/427811d8-09ca-4a8d-8fdc-98cdaf5b7033.png" alt="Correlation heatmap showing the relationship between the selected variables" class="image--center mx-auto" width="1174" height="913" loading="lazy"></p>
<p>Correlation coefficient ranges from -1 to 1, where values less than 0 mean a negative relationship, while those above 0 mean a positive relationship. The lower the value in a negative relationship, the stronger the negative relationship, while the higher the value in a positive relationship, the stronger the relationship.</p>
<p>Based on the plot above, here are the key insights:</p>
<ul>
<li><p><strong>Views and watch time</strong>: There's a strong correlation (0.94) between views and watch time, suggesting that as videos get more views, they also accumulate more watch hours, proportionally.</p>
</li>
<li><p><strong>Views and impressions</strong>: There's a strong correlation (0.89) between views and impressions, indicating that videos that are shown more frequently in recommendations and search results tend to get more views.</p>
</li>
<li><p><strong>Average view duration</strong>: This metric has very weak correlations with almost all other metrics. It is particularly notable in views (0.06), subscribers (0.01), and impressions (0.03).</p>
</li>
<li><p><strong>Subscribers and metrics</strong>: Subscribers have a moderate to strong correlation with views (0.75) and impressions (0.79) and a weaker correlation with click-through rate (0.54).</p>
</li>
<li><p><strong>Click-through rate</strong>: Has moderate correlations with views (0.69) and watch time (0.66) but a weaker correlation with subscribers (0.54).</p>
</li>
</ul>
<p>The most significant insight is that average view duration appears to operate independently from other metrics. This suggests that on my YouTube channel, a video's ability to retain viewers throughout its length isn't necessarily connected to how many people watch it, how often it's recommended, or how many subscribers the channel has.</p>
<p>This implies that the strategies I would implement to increase my views, subscribers, and impressions might differ from those needed to improve average view duration, an important factor in YouTube's recommendation algorithm. This means I need to look at other YouTube metrics that have a relationship with average view duration, which is a topic for another article.</p>
<h3 id="heading-audience-retention-analysis">Audience Retention Analysis</h3>
<p>To analyze audience retention, we need to create a new variable <code>Retention Rate (%)</code>, which is calculated by dividing a video’s <code>Average view duration</code> by the <code>Duration</code> and expressing it as a percentage.</p>
<pre><code class="lang-python">
<span class="hljs-comment"># Calculate retention rate as (Average View Duration / Total Video Duration) * 100</span>
df[<span class="hljs-string">'Retention Rate (%)'</span>] = (df[<span class="hljs-string">'Average view duration'</span>] / df[<span class="hljs-string">'Duration'</span>]) * <span class="hljs-number">100</span>
</code></pre>
<p>Next is to sort the videos in ascending order based on <code>Retention Rate (%)</code> and display the top 10 videos with the highest retention rate.</p>
<pre><code class="lang-python"><span class="hljs-comment"># Sort videos by retention rate</span>
df_sorted = df.sort_values(by=<span class="hljs-string">'Retention Rate (%)'</span>, ascending=<span class="hljs-literal">False</span>)

<span class="hljs-comment"># Display top 10 videos with highest retention</span>
df_sorted[[<span class="hljs-string">'Video title'</span>, <span class="hljs-string">'Duration'</span>, <span class="hljs-string">'Average view duration'</span>, <span class="hljs-string">'Retention Rate (%)'</span>]].head(<span class="hljs-number">10</span>)
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742634265073/fc5bac65-18f3-467a-a8da-85f95ae00488.png" alt="Image showing top ten videos by retention rate" class="image--center mx-auto" width="1194" height="550" loading="lazy"></p>
<p>From the table above, you will notice that most of the videos in the top 10 spot are not above 503 seconds, which is approximately 8 minutes. This implies that my audience are interested in short, mid-range videos.</p>
<p>Most videos with the high retention rate have a duration less than 4 minutes, with a retention rate ranging from 27% - 40%. With this insight, I can ensure that the next videos I will upload are within 5 to 8 minutes.</p>
<p>Let’s take a look at the bottom 10 videos with a low retention rate:</p>
<pre><code class="lang-python"><span class="hljs-comment"># Sort videos by retention rate</span>
df_sorted = df.sort_values(by=<span class="hljs-string">'Retention Rate (%)'</span>, ascending=<span class="hljs-literal">False</span>)

<span class="hljs-comment"># Display bottom 10 videos with highest retention</span>
df_sorted[[<span class="hljs-string">'Video title'</span>, <span class="hljs-string">'Duration'</span>, <span class="hljs-string">'Average view duration'</span>, <span class="hljs-string">'Retention Rate (%)'</span>]].tail(<span class="hljs-number">10</span>)
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742634531458/28b1d8e8-38d9-480e-8259-a30f659386a3.png" alt="Image showing bottom ten videos by retention rate" class="image--center mx-auto" width="1168" height="538" loading="lazy"></p>
<p>From the above information, you will notice that long videos in my channel spanning approximately 22 - 58 minutes have a low retention rate. This further supports the claim above that my audience is more interested in shorter videos.</p>
<p>We can further decide to plot a scattered plot of <code>Duration</code> against <code>Retention Rate (%)</code> to summarize the above tables.</p>
<pre><code class="lang-python"><span class="hljs-comment"># Set style for plots</span>
sns.set_style(<span class="hljs-string">"whitegrid"</span>)

<span class="hljs-comment"># Plot Retention Rate vs. Video Duration</span>
plt.figure(figsize=(<span class="hljs-number">12</span>, <span class="hljs-number">6</span>))

sns.scatterplot(data=df, x=<span class="hljs-string">'Duration'</span>, y=<span class="hljs-string">'Retention Rate (%)'</span>, hue=<span class="hljs-string">'Views'</span>, size=<span class="hljs-string">'Views'</span>, sizes=(<span class="hljs-number">20</span>, <span class="hljs-number">200</span>), palette=<span class="hljs-string">'coolwarm'</span>)
plt.title(<span class="hljs-string">"Audience Retention vs. Video Duration"</span>)
plt.xlabel(<span class="hljs-string">"Video Duration (seconds)"</span>)
plt.ylabel(<span class="hljs-string">"Retention Rate (%)"</span>)
plt.legend(title=<span class="hljs-string">"Views"</span>, loc=<span class="hljs-string">"upper right"</span>)

plt.show()
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742634776775/e024b61c-d86f-45d6-b8fb-13ff87e101e9.png" alt="Scatter plot showing audience retention against video duration" class="image--center mx-auto" width="1486" height="820" loading="lazy"></p>
<p>The <a target="_blank" href="https://byjus.com/commerce/scatter-diagram/">scatter plot</a> above shows the relationship between audience retention rate (y-axis, measured as a percentage) and video duration (x-axis, measured in seconds) for various videos. Here are the following key observations:</p>
<ul>
<li><p>There's a clear negative correlation between video duration and retention rate – as videos get longer, the retention rate generally decreases.</p>
</li>
<li><p>The highest retention rates (35-40%) are found in shorter videos, mostly under 500 seconds (around 8 minutes).</p>
</li>
<li><p>Videos over 1500 seconds (25 minutes) consistently show retention rates below 15%.</p>
</li>
<li><p>The size and color of the dots represent the number of views, with larger, redder dots indicating more views (up to 1000) and smaller, blue dots representing fewer views (around 200).</p>
</li>
<li><p>Interestingly, some mid-length videos (around 500 seconds) have both higher view counts (indicated by larger red dots) and decent retention rates of about 25%.</p>
</li>
<li><p>The longest video in the dataset (at around 3500 seconds or 58 minutes) has a retention rate of about 14% and relatively few views.</p>
</li>
</ul>
<p>This plot further confirms the claim that shorter videos tend to better maintain audience attention on my channel, though some mid-length videos can still perform well in terms of both retention and view count.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>What we’ve learned from my data is just the tip of the iceberg. YouTube has many metrics, and because my channel is not monetized and has few subscribers and videos, I don’t have data on monetization, demographics, and other metrics.</p>
<p>But after reading this article, I hope that you can think of endless information you want to get based on these metrics. You can even forecast your views, subscriber counts, and revenue for the next days or months. You can also perform a multivariate time series analysis to see how these factors affect your primary variable of interest.</p>
<p>If you find this article interesting, don’t forget to check out my <a target="_blank" href="https://learndata.xyz/blog">blog</a> for other interesting articles, follow me on <a target="_blank" href="https://medium.com/@adejumo999">Medium</a>, connect on <a target="_blank" href="https://www.linkedin.com/in/adejumoridwan/">LinkedIn</a>, and subscribe to my <a target="_blank" href="http://www.youtube.com/@learndata_xyz">YouTube channel</a>.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Create a DeepSeek R1 API in R with Plumber ]]>
                </title>
                <description>
                    <![CDATA[ To create an AI chatbot and integrate it with another platform, you have to communicate with large language model using an API. This API receives prompts from the client and sends them to the model to generate answers. In this tutorial, you will lear... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-create-a-deepseek-r1-api-in-r-with-plumber/</link>
                <guid isPermaLink="false">67b7b91a534c03e678009324</guid>
                
                    <category>
                        <![CDATA[ Data Science ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Machine Learning ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Deep Learning ]]>
                    </category>
                
                    <category>
                        <![CDATA[ APIs ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Adejumo Ridwan Suleiman ]]>
                </dc:creator>
                <pubDate>Thu, 20 Feb 2025 23:22:01 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1740093558918/453118b9-3c93-4e57-a1ad-7471e1046ef1.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>To create an AI chatbot and integrate it with another platform, you have to communicate with large language model using an API. This API receives prompts from the client and sends them to the model to generate answers.</p>
<p>In this tutorial, you will learn how to create such an API using the DeepSeek R1 large language model so external applications can call it. We will use the <a target="_blank" href="https://huggingface.co/deepseek-ai/DeepSeek-R1">DeepSeek R1 model</a>, available on HuggingFace, and the Plumber R package to deploy it as an API.</p>
<p>HuggingFace is an open source platform for building, training, and deploying machine learning models, while Plumber is an R package that expose R code as a RESTful APIs accessible to other applications through HTTP requests.</p>
<p>With this API, you can:</p>
<ul>
<li><p>Build AI applications</p>
</li>
<li><p>Connect to external data and extract meaningful insights</p>
</li>
<li><p>Integrate into existing applications to provide customer support, create documentations, and so on.</p>
</li>
</ul>
<h2 id="heading-what-is-the-deepseek-r1-model">What is the DeepSeek R1 Model?</h2>
<p>DeepSeek R1 is the latest large language model from the Chinese company <a target="_blank" href="https://www.deepseek.com/">DeepSeek</a>. It was designed to enhance the problem-solving and analytic capabilities of AI systems.</p>
<p>DeepSeek-R1 uses reinforcement learning and supervised fine-tuning to handle complex reasoning tasks. Unlike proprietary models, DeepSeek R1 is open-source and free to use.</p>
<h2 id="heading-prerequisites">Prerequisites</h2>
<ul>
<li><p>Sign up for a <a target="_blank" href="https://huggingface.co/">HuggingFace account</a> if you don’t already have one</p>
</li>
<li><p>Install <a target="_blank" href="https://posit.co/download/rstudio-desktop/">R and R Studio</a>.</p>
</li>
<li><p>Install the <a target="_blank" href="https://www.rplumber.io/"><code>plumber</code></a> R package to build the API endpoint</p>
</li>
<li><p>Install the <a target="_blank" href="https://httr2.r-lib.org/"><code>httr2</code></a> R package to work with HTTP requests and interact with the Hugging Face API</p>
</li>
</ul>
<h2 id="heading-step-1-create-your-project-repository">Step 1: Create Your Project Repository</h2>
<p>You need to create an R project to create an API application in R. This ensures that all the files needed to keep your API working are kept together under the same directory. R Studio already has a template provided for API projects, so you can follow the steps below to create yours.</p>
<p>In your R Studio IDE, click on the File menu and go to New Project to open the New Project Wizard. Once in the wizard, select New Directory, then click New Plumber API Project. Inside the directory name field, give it a name (for example <code>DeepSeek-R1 API</code>), and then click on Create Project.</p>
<p>You will see a file called <code>plumber.R</code> with a sample API template. This is where you’ll write the code to connect to the DeepSeek R1 model on HuggingFace. Make sure that you clear this template before proceeding.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738503866976/60b959cd-b564-486d-8b65-c9ca0278e239.gif" alt="GIF showing how to create a new Plumber project in R" class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<p>Next, go to your terminal and create a <code>.env</code> file. This is where you will store the Hugging Face API key.</p>
<pre><code class="lang-plaintext">touch .env
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738504109388/6ce9bda3-305a-4f2e-87b8-adbe4c245861.png" alt="Image showing how to create a .env variable on the terminal" class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<p>Create a <code>.gitignore</code> file and add the <code>.env</code> file to it. This ensures that sensitive information like access tokens and API keys are not pushed to your Git repository.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738504889229/0d433bcb-2a7d-4379-a0c7-e09fb53e288f.png" alt="Image showing the .env file in the .gitignore file" class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<h2 id="heading-step-2-create-a-hugging-face-access-token">Step 2: Create a Hugging Face Access Token</h2>
<p>We need to create an access token to connect to Hugging Face models. Go to your profile, click Settings, and click Create New Token to create your access token for the Hugging Face repository.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738504360986/077a2778-d790-4ff9-94e1-c2c372b2efef.png" alt="Image showing the access tokens page, with options to create a new token " class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<p>Copy the access token and paste it into your <code>.env</code> file, and give it the name <code>HUGGINGFACE_ACCESS_TOKEN</code>.</p>
<pre><code class="lang-plaintext">HUGGINGFACE_ACCESS_TOKEN="&lt;your-access-token&gt;"
</code></pre>
<p>Next is to install the <code>dotenv</code> package, and paste the following code at the top of your <code>plumber.R</code> file:</p>
<pre><code class="lang-r"><span class="hljs-comment"># Load environment variables from .env</span>
dotenv::load_dot_env()
</code></pre>
<p><code>dotenv::load_dot_env()</code> loads all environment variables in the <code>.env</code> file, making them available to the <code>plumber.R</code> script.</p>
<h2 id="heading-step-3-build-the-deepseek-api-endpoint">Step 3: Build the DeepSeek API Endpoint</h2>
<p>Now that we have our project environment set up and API token ready, we’ll write the code to build the API application by connecting to the DeepSeek R1 model on HuggingFace.</p>
<p>Go to the <code>plumber.R</code> file and load the following libraries:</p>
<pre><code class="lang-r"><span class="hljs-keyword">library</span>(plumber)
<span class="hljs-keyword">library</span>(httr2)
</code></pre>
<p>Copy and paste the following code into <code>plumber.R</code>:</p>
<pre><code class="lang-r">
api_key &lt;- Sys.getenv(<span class="hljs-string">"HUGGINGFACE_ACCESS_TOKEN"</span>)



<span class="hljs-comment">#* @post /deepseek_chat</span>
<span class="hljs-keyword">function</span>(prompt) {
  url &lt;- <span class="hljs-string">"https://huggingface.co/api/inference-proxy/together/v1/chat/completions"</span>

  <span class="hljs-comment"># Create a request object</span>
  req &lt;- request(url) |&gt;
    req_auth_bearer_token(api_key) |&gt;
    req_body_json(list(
      model = <span class="hljs-string">"deepseek-ai/DeepSeek-R1"</span>,
      messages = list(
        list(role = <span class="hljs-string">"user"</span>, content = prompt)
      ),
      max_tokens = <span class="hljs-number">500</span>,
      stream = <span class="hljs-literal">FALSE</span>
    ))

  <span class="hljs-comment"># Perform the request and capture the response</span>
  res &lt;- req_perform(req)

  <span class="hljs-comment"># Parse the JSON response</span>
  parsed_data &lt;- res |&gt;
    resp_body_json()

  <span class="hljs-comment"># Extract the content from the response</span>
  content &lt;- parsed_data$choices
  <span class="hljs-keyword">return</span>(content)
}
</code></pre>
<p>Here’s what’s going on in the above code:</p>
<ul>
<li><p><code>Sys.getenv</code> gets the HuggingFace access token and stores it in the variable <code>access_token</code>.</p>
</li>
<li><p>The <code>url</code> variable contains the API link to access the DeepSeek model on HuggingFace. You can get this by searching the model name <code>deepseek-ai/DeepSeek-R1</code> on HuggingFace. Go to the <strong>View Code</strong> button, and under the <strong>cURL</strong> tab, copy the API URL</p>
<p>  <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1739177037117/0781bce2-7bf8-411d-ad71-cb2bf11fe1bb.gif" alt="GIF showing how to copy the API url you are going to use in your plumber API code" width="600" height="400" loading="lazy"></p>
</li>
<li><p><code>#* @post /deepseek_chat</code> means that the endpoint makes a POST request through the path <code>/deepseek_chat</code>.</p>
</li>
<li><p>This endpoint takes an argument <code>prompt</code>, a text, or a question a user is expected to give.</p>
</li>
<li><p>The <code>req</code> object is a chain of various operations, which makes a <code>request()</code> to the <code>url</code>, and then takes the <code>api_key</code> inside the <code>req_auth_bearer_token()</code> function. Model properties such as <code>model</code> name, <code>role</code>, <code>prompt</code>, and <code>max_tokens</code> are passed to the <code>req</code> object through the <code>req_body_json</code> function.</p>
</li>
<li><p>The <code>headers</code> variable contains the authorization required to make a request to HuggingFace API.</p>
</li>
<li><p>The request is performed and captured in a response object <code>res</code> using the <code>req_perform()</code> function.</p>
</li>
<li><p>The <code>res</code> object returns a JSON object, which is now parsed to R using the<code>resp_body_json()</code> function.</p>
</li>
<li><p>The <code>content</code> of the <code>parsed_data</code> is now returned so you can extract the information you need from the application for which you want to use the API.</p>
</li>
</ul>
<h2 id="heading-step-4-test-the-api-endpoint">Step 4: Test the API Endpoint</h2>
<p>Let’s run the API endpoint to see how the application performs. Click on Run API. This will automatically open the API endpoint on your browser on the URL <a target="_blank" href="http://127.0.0.1:8634/docs/"><code>http://127.0.0.1:8634/docs/</code></a>.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1739282692303/82a029ea-31f5-4088-9e72-2fe1b69d0f7d.png" alt="Image showing the Run API button" class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<p>Click on the API endpoint dropdown, provide a prompt, and click the Execute button. You should receive a reply in a few minutes.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1739282620577/b1a52679-b397-4d82-af56-0f81ebc5888e.gif" alt="Image showing how the API endpoint returns a response when a prompt is given" class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>With your API, you can make inferences to the Hugging Face model and build AI applications in R or other programing languages. You need to host your API to make it accessible to clients online. There are various <a target="_blank" href="https://www.rplumber.io/articles/hosting.html">ways of hosting an R Plumber application</a>: you can use Docker or host it on DigitalOcean using the plumberDeploy R package. However, the simplest and easiest way is to use <a target="_blank" href="https://posit.co/products/enterprise/connect/">Posit Connect</a>.</p>
<p>You can use the same approach used in this tutorial to try out other HuggingFace models, build an API to generate images or translate different languages. R Plumber is easy to use, and the documentation provides many resources.</p>
<p>If you are interested in model deployment using R Plumber, you can check out <a target="_blank" href="https://learndata.xyz/posts/forecasting%20time%20series%20data%20with%20facebook%20prophet/">this article</a> on how to deploy a Time Series model built on Prophet using R Plumber.</p>
<p>If you find this article interesting, please check my other articles on <a target="_blank" href="https://learndata.xyz/blog">learndata.xyz</a>.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Build a Calculator App with Svelte ]]>
                </title>
                <description>
                    <![CDATA[ Svelte is an open-source front-end JavaScript framework used for building web applications, designed to make developing interactive user interfaces more efficient and performant. Compared to other front-end frameworks like React, Vue, or Angular, it ... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-build-a-calculator-app-with-svelte/</link>
                <guid isPermaLink="false">66d45d583dce891ac3a967a6</guid>
                
                    <category>
                        <![CDATA[ JavaScript ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Svelte ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Adejumo Ridwan Suleiman ]]>
                </dc:creator>
                <pubDate>Tue, 22 Aug 2023 15:48:35 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2023/08/WHATSAPP-DICTIONARY-CHATBOT--1-.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Svelte is an open-source front-end JavaScript framework used for building web applications, designed to make developing interactive user interfaces more efficient and performant.</p>
<p>Compared to other front-end frameworks like React, Vue, or Angular, it focuses on a different approach by compiling components.</p>
<p>In most traditional frameworks, you build components using a virtual DOM (Document Object Model) abstraction.</p>
<p>In these frameworks, changes to the UI are first made to a virtual representation of the UI which calculates the differences and updates the actual DOM accordingly. This process can introduce overhead and performance bottlenecks, especially for complex applications.</p>
<p>Svelte, on the other hand, takes a different approach.</p>
<p>It shifts much of the work to the build process, compiling components into highly optimized JavaScript code that directly manipulates the DOM during runtime.</p>
<p>Svelte applications have a smaller runtime footprint and can often achieve better performance compared to applications built with traditional frameworks.</p>
<p>In this tutorial, you will learn how to build a simple calculator using Svelte.</p>
<p>Unlike most frameworks, Svelte does not have a steep learning curve. A basic understanding of HTML, CSS and JavaScript is sufficient to grasp Svelte.</p>
<p>The following are the prerequisites for this tutorial:</p>
<ul>
<li><p>Basic knowledge of HTML, CSS and JavaScript</p>
</li>
<li><p>Willingness to learn</p>
</li>
</ul>
<p>You can experience how the calculator works <a target="_blank" href="https://svelte.dev/repl/cdf560babcf148639631872f27ba3275?version=4.2.0">here</a>.</p>
<h2 id="heading-how-to-plan-the-project">How to Plan the Project</h2>
<p>Those who fail to plan, plan to fail. It's a good practice to plan what you are building.</p>
<p>We want the calculator application to follow some criteria as follows:</p>
<ul>
<li><p>The calculator should have a user-friendly interface with buttons for digits (0-9), decimal point (.), and arithmetic operations (+, -, *, /).</p>
</li>
<li><p>It should display the current input and the result on the screen.</p>
</li>
<li><p>The calculator should support multiple arithmetic operations in sequence (for example: 2 + 3 * 5).</p>
</li>
<li><p>The user should be able to clear the input and reset the calculator.</p>
</li>
<li><p>The calculator should handle edge cases and prevent invalid inputs.</p>
</li>
</ul>
<p>Below is a design of how the calculator should look like. You can use tools like <a target="_blank" href="https://www.figma.com/">Figma</a> or <a target="_blank" href="https://helpx.adobe.com/xd/get-started.html">Adobe XD</a> to draw how you want your UI to look or sketch it on paper.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/08/image-118.png" alt="Image of the proposed Calculator to be built" width="600" height="400" loading="lazy"></p>
<h2 id="heading-how-to-build-the-user-interface">How to Build the User Interface</h2>
<p>The calculator you will build is a simple app using <a target="_blank" href="https://svelte.dev/repl/hello-world?version=4.2.0">Svelte REPL</a>. It's an interactive coding environment that allows you to play with Svelte without going through the hassle of getting it set up locally on your PC.</p>
<p>But if you to prefer to follow locally, ensure you have <a target="_blank" href="https://nodejs.org/en">Node.js</a> installed, and run the following code on your terminal:</p>
<pre><code class="lang-shell">npm create svelte@latest &lt;name-of-your-app&gt;
cd myapp
npm install
npm run dev
</code></pre>
<p>You can read more <a target="_blank" href="https://svelte.dev/docs/introduction">here</a> on how to get started.</p>
<p>Svelte allows you to build apps based on components written in a <code>.svelte file</code>. A web application contains components such as buttons, headers and so on.</p>
<p>Svelte simplifies this process by allowing you to create it once and reuse it in any part of your application. Most web applications contain one or more components.</p>
<p>The main application is in <code>App.svelte</code>, which contains the main code for the calculator app you are about to build.</p>
<p>When you open the <a target="_blank" href="https://svelte.dev/repl/hello-world?version=4.2.0">Svelte REPL</a>, you can see the default application prints <em>Hello World</em> on the screen:</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">script</span>&gt;</span><span class="javascript">
    <span class="hljs-keyword">let</span> name = <span class="hljs-string">'world'</span>;
</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>

<span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>Hello {name}!<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/08/image-119.png" alt="Image displaying the Hello World app" width="600" height="400" loading="lazy"></p>
<p>A <code>.svelte</code> file contains JavaScript, HTML and CSS.</p>
<p>The JavaScript, is written in the <code>&lt;script&gt;...&lt;/script&gt;</code> tag, while you can write the HTML code below it, and apply CSS styling in the <code>&lt;style&gt;...&lt;/style&gt;</code> tag.</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">script</span>&gt;</span><span class="javascript">
    <span class="hljs-keyword">let</span> name = <span class="hljs-string">'world'</span>;
</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>

<span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>Hello {name}!<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">style</span>&gt;</span><span class="css">
    <span class="hljs-selector-tag">h1</span>{
        <span class="hljs-attribute">background</span>: red;
    }
</span><span class="hljs-tag">&lt;/<span class="hljs-name">style</span>&gt;</span>
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/08/image-120.png" alt="Image of the result of the above code, Hello World is printed with a red background" width="600" height="400" loading="lazy"></p>
<p>Variables declared in the script tag are displayed using the curly parentheses <code>{}</code>. Just like you can see <code>Hello Word</code> displayed using the <code>name</code> variable.</p>
<p>Now let's start building the application, copy and paste the following code into <code>App.svelte</code>:</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">script</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>

<span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"calculator"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"display"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"buttons"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">button</span>&gt;</span>7<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">button</span>&gt;</span>8<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">button</span>&gt;</span>9<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"operator"</span>&gt;</span>+<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">button</span>&gt;</span>4<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">button</span>&gt;</span>5<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">button</span>&gt;</span>6<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"operator"</span>&gt;</span>-<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">button</span>&gt;</span>1<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">button</span>&gt;</span>2<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">button</span>&gt;</span>3<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"operator"</span>&gt;</span>*<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">button</span>&gt;</span>0<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">button</span>&gt;</span>.<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"clear"</span>&gt;</span>C<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"operator"</span>&gt;</span>/<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"equals"</span>&gt;</span>=<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>

<span class="hljs-tag">&lt;<span class="hljs-name">style</span>&gt;</span>

<span class="hljs-tag">&lt;/<span class="hljs-name">style</span>&gt;</span>
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/08/image-121.png" alt="Image showing result of the above code, the buttons are all layed out horizontally without any styling" width="600" height="400" loading="lazy"></p>
<p>If you have done that, you have created two divs – <code>calculator</code> and <code>display</code>. <code>calculator</code> is the parent div that contains <code>display</code> and the calculator <code>buttons</code>.</p>
<p>All arithmetic operations carry the class name <code>operator</code>. The clear sign also has the class name <code>clear</code>, and the equal sign has the class name <code>equals</code>.</p>
<p>You might not see the display now because we haven't applied CSS styling.</p>
<p>Inside the <code>&lt;style&gt;&lt;/style&gt;</code> tag, paste the code below:</p>
<pre><code class="lang-javascript">&lt;script&gt;

&lt;/script&gt;

...

&lt;style&gt;
.calculator {
    <span class="hljs-attr">display</span>: inline-block;
    border: <span class="hljs-number">1</span>px solid #ccc;
    padding: <span class="hljs-number">10</span>px;
    border-radius: <span class="hljs-number">5</span>px;
    box-shadow: <span class="hljs-number">0</span> <span class="hljs-number">2</span>px <span class="hljs-number">5</span>px rgba(<span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0.1</span>);
}

.display {
    font-size: <span class="hljs-number">24</span>px;
    border: <span class="hljs-number">1</span>px solid #ccc;
    height: <span class="hljs-number">24</span>px;
    padding: <span class="hljs-number">10</span>px;
    margin-bottom: <span class="hljs-number">10</span>px;
    width: <span class="hljs-number">300</span>px;
    text-align: right;
}
&lt;/style&gt;
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/08/image-122.png" alt="Image showing the styling applied on the two divs calculator and display" width="600" height="400" loading="lazy"></p>
<p>Now let's style the buttons into a grid of four columns.</p>
<p>Update the <code>&lt;style&gt;&lt;/style&gt;</code> tag with the <code>buttons</code> and <code>button</code> style below:</p>
<pre><code class="lang-html">...

<span class="hljs-tag">&lt;<span class="hljs-name">style</span>&gt;</span><span class="css">
 ...
<span class="hljs-selector-class">.buttons</span> {
    <span class="hljs-attribute">display</span>: grid;
    <span class="hljs-attribute">grid-template-columns</span>: <span class="hljs-built_in">repeat</span>(<span class="hljs-number">4</span>, <span class="hljs-number">75px</span>);
    <span class="hljs-attribute">gap</span>: <span class="hljs-number">5px</span>;
}

<span class="hljs-selector-tag">button</span> {
    <span class="hljs-attribute">padding</span>: <span class="hljs-number">10px</span>;
    <span class="hljs-attribute">font-size</span>: <span class="hljs-number">18px</span>;
    <span class="hljs-attribute">border</span>: none;
    <span class="hljs-attribute">cursor</span>: pointer;
    <span class="hljs-attribute">border-radius</span>: <span class="hljs-number">5px</span>;
    <span class="hljs-attribute">font-family</span>: Arial, sans-serif;
    <span class="hljs-attribute">text-align</span>: center;
}
</span><span class="hljs-tag">&lt;/<span class="hljs-name">style</span>&gt;</span>
</code></pre>
<p>Note that <code>buttons</code> is the class name for the div containing the various HTML <code>button</code> tags.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/08/image-123.png" alt="Image displaying the 4 column grid of the buttons div" width="600" height="400" loading="lazy"></p>
<p>Next, let's style the buttons to improve user experience for anyone using the calculator and make the equal button occupy the empty spaces.</p>
<p>Update the <code>&lt;style&gt;&lt;/style&gt;</code> tag as follows:</p>
<pre><code class="lang-html">...
<span class="hljs-tag">&lt;<span class="hljs-name">style</span>&gt;</span><span class="css">
 ...
 <span class="hljs-selector-class">.operator</span>{
    <span class="hljs-attribute">border</span>: <span class="hljs-number">0px</span> solid <span class="hljs-number">#A46D19</span>;
    <span class="hljs-attribute">background</span>: <span class="hljs-number">#F90</span>;
}
<span class="hljs-selector-class">.clear</span>{
    <span class="hljs-attribute">border</span>: <span class="hljs-number">0px</span> solid <span class="hljs-number">#000</span>;
    <span class="hljs-attribute">background</span>: red;
}
<span class="hljs-selector-class">.equals</span>{
    <span class="hljs-attribute">border</span>: <span class="hljs-number">0px</span> solid <span class="hljs-number">#000</span>;
    <span class="hljs-attribute">background</span>: <span class="hljs-number">#245BE9</span>;
    <span class="hljs-attribute">width</span>: <span class="hljs-number">320px</span>
}
</span><span class="hljs-tag">&lt;/<span class="hljs-name">style</span>&gt;</span>
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/08/image-124.png" alt="Image showing the calculator ui, with an orange colour giving to the aritmetic buttons, red to the clear button and blue to the equal sign button. The equal sign button is also extended to fill up the space shown earlier" width="600" height="400" loading="lazy"></p>
<p>Not done yet, one last thing to do.</p>
<p>You need to include hovering effect on all buttons, allowing a user to know when the mouse is on a particular button. This will make for a better user experience.</p>
<p>Update the <code>&lt;style&gt;&lt;/style&gt;</code> tag as follows:</p>
<pre><code class="lang-html">...
<span class="hljs-tag">&lt;<span class="hljs-name">style</span>&gt;</span><span class="css">
    ...
<span class="hljs-selector-class">.operator</span><span class="hljs-selector-pseudo">:hover</span>{
    <span class="hljs-attribute">background</span>: <span class="hljs-number">#FFD700</span>;
}
<span class="hljs-selector-class">.clear</span><span class="hljs-selector-pseudo">:hover</span> {
    <span class="hljs-attribute">background</span>: <span class="hljs-number">#FFC0CB</span> ;
}
<span class="hljs-selector-class">.equals</span><span class="hljs-selector-pseudo">:hover</span> {
    <span class="hljs-attribute">background</span>: <span class="hljs-number">#ADD8E6</span>; 
}
</span><span class="hljs-tag">&lt;/<span class="hljs-name">style</span>&gt;</span>
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/08/image-125.png" alt="Image showin hovering effect on the equals sign" width="600" height="400" loading="lazy"></p>
<p>Now we are done with the calculator's user interface.</p>
<p>If you did everything right, your code should look like this:</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">script</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>

<span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"calculator"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"display"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"buttons"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">button</span>&gt;</span>7<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">button</span>&gt;</span>8<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">button</span>&gt;</span>9<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"operator"</span>&gt;</span>+<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">button</span>&gt;</span>4<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">button</span>&gt;</span>5<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">button</span>&gt;</span>6<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"operator"</span>&gt;</span>-<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">button</span>&gt;</span>1<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">button</span>&gt;</span>2<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">button</span>&gt;</span>3<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"operator"</span>&gt;</span>*<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">button</span>&gt;</span>0<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">button</span>&gt;</span>.<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"clear"</span>&gt;</span>C<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"operator"</span>&gt;</span>/<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"equals"</span>&gt;</span>=<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>

<span class="hljs-tag">&lt;<span class="hljs-name">style</span>&gt;</span><span class="css">
<span class="hljs-selector-class">.calculator</span> {
    <span class="hljs-attribute">display</span>: inline-block;
    <span class="hljs-attribute">border</span>: <span class="hljs-number">1px</span> solid <span class="hljs-number">#ccc</span>;
    <span class="hljs-attribute">padding</span>: <span class="hljs-number">10px</span>;
    <span class="hljs-attribute">border-radius</span>: <span class="hljs-number">5px</span>;
    <span class="hljs-attribute">box-shadow</span>: <span class="hljs-number">0</span> <span class="hljs-number">2px</span> <span class="hljs-number">5px</span> <span class="hljs-built_in">rgba</span>(<span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0.1</span>);
}

<span class="hljs-selector-class">.display</span> {
    <span class="hljs-attribute">font-size</span>: <span class="hljs-number">24px</span>;
    <span class="hljs-attribute">border</span>: <span class="hljs-number">1px</span> solid <span class="hljs-number">#ccc</span>;
    <span class="hljs-attribute">height</span>: <span class="hljs-number">24px</span>;
    <span class="hljs-attribute">padding</span>: <span class="hljs-number">10px</span>;
    <span class="hljs-attribute">margin-bottom</span>: <span class="hljs-number">10px</span>;
    <span class="hljs-attribute">width</span>: <span class="hljs-number">300px</span>;
    <span class="hljs-attribute">text-align</span>: right;
}
<span class="hljs-selector-class">.buttons</span> {
    <span class="hljs-attribute">display</span>: grid;
    <span class="hljs-attribute">grid-template-columns</span>: <span class="hljs-built_in">repeat</span>(<span class="hljs-number">4</span>, <span class="hljs-number">75px</span>);
    <span class="hljs-attribute">gap</span>: <span class="hljs-number">5px</span>;
}

<span class="hljs-selector-tag">button</span> {
    <span class="hljs-attribute">padding</span>: <span class="hljs-number">10px</span>;
    <span class="hljs-attribute">font-size</span>: <span class="hljs-number">18px</span>;
    <span class="hljs-attribute">border</span>: none;
    <span class="hljs-attribute">cursor</span>: pointer;
    <span class="hljs-attribute">border-radius</span>: <span class="hljs-number">5px</span>;
    <span class="hljs-attribute">font-family</span>: Arial, sans-serif;
    <span class="hljs-attribute">text-align</span>: center;
}
<span class="hljs-selector-class">.operator</span>{
    <span class="hljs-attribute">border</span>: <span class="hljs-number">0px</span> solid <span class="hljs-number">#A46D19</span>;
    <span class="hljs-attribute">background</span>: <span class="hljs-number">#F90</span>;
}
<span class="hljs-selector-class">.clear</span>{
    <span class="hljs-attribute">border</span>: <span class="hljs-number">0px</span> solid <span class="hljs-number">#000</span>;
    <span class="hljs-attribute">background</span>: red;
}
<span class="hljs-selector-class">.equals</span>{
    <span class="hljs-attribute">border</span>: <span class="hljs-number">0px</span> solid <span class="hljs-number">#000</span>;
    <span class="hljs-attribute">background</span>: <span class="hljs-number">#245BE9</span>;
    <span class="hljs-attribute">width</span>: <span class="hljs-number">320px</span>
}
<span class="hljs-selector-class">.operator</span><span class="hljs-selector-pseudo">:hover</span>{
    <span class="hljs-attribute">background</span>: <span class="hljs-number">#FFD700</span>;
}
<span class="hljs-selector-class">.clear</span><span class="hljs-selector-pseudo">:hover</span> {
    <span class="hljs-attribute">background</span>: <span class="hljs-number">#FFC0CB</span> ;
}
<span class="hljs-selector-class">.equals</span><span class="hljs-selector-pseudo">:hover</span> {
    <span class="hljs-attribute">background</span>: <span class="hljs-number">#ADD8E6</span>; 
}
</span><span class="hljs-tag">&lt;/<span class="hljs-name">style</span>&gt;</span>
</code></pre>
<p>Now let's start cooking!</p>
<h2 id="heading-how-to-handle-interactivity">How to Handle Interactivity</h2>
<p>Now that you have finished with the UI, let's make the calculator interactive by starting with the number buttons.</p>
<p>Copy and paste the following code into the <code>&lt;script&gt;&lt;/script&gt;</code> tag in <code>App.svelte</code>:</p>
<pre><code class="lang-javascript">&lt;script&gt;
    <span class="hljs-keyword">let</span> display_number = <span class="hljs-string">""</span>;
    <span class="hljs-keyword">const</span> select = <span class="hljs-function">(<span class="hljs-params">num</span>) =&gt;</span> <span class="hljs-function">() =&gt;</span> (display_number += num);
    <span class="hljs-keyword">const</span> clear = <span class="hljs-function">() =&gt;</span> (display_number = <span class="hljs-string">""</span>);
&lt;/script&gt;
...
...
</code></pre>
<ul>
<li><p><code>display_number</code> is the number displayed on the calculator screen.</p>
</li>
<li><p><code>select</code> is the function that allows any number clicked, to appear on the screen.</p>
</li>
<li><p><code>clear</code> is the function that clears the screen, resetting the value of display number to an empty string.</p>
</li>
</ul>
<p>Note that <code>display_number</code> is a string data type. Later on you will learn how to convert it to a numeric data type and perform calculations with it.</p>
<p>Next let's implement the <code>select</code> and <code>clear</code> function into the HTML.</p>
<p>Modify the HTML as follows:</p>
<pre><code class="lang-html">...
<span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"calculator"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"display"</span>&gt;</span>{display_number}<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"buttons"</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">on:click</span>=<span class="hljs-string">{select(7)}</span>&gt;</span>7<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">on:click</span>=<span class="hljs-string">{select(8)}</span>&gt;</span>8<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">on:click</span>=<span class="hljs-string">{select(9)}</span>&gt;</span>9<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"operator"</span> &gt;</span>+<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">on:click</span>=<span class="hljs-string">{select(4)}</span>&gt;</span>4<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">on:click</span>=<span class="hljs-string">{select(5)}</span>&gt;</span>5<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">on:click</span>=<span class="hljs-string">{select(6)}</span>&gt;</span>6<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"operator"</span> &gt;</span>-<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">on:click</span>=<span class="hljs-string">{select(1)}</span>&gt;</span>1<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">on:click</span>=<span class="hljs-string">{select(2)}</span>&gt;</span>2<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">on:click</span>=<span class="hljs-string">{select(3)}</span>&gt;</span>3<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"operator"</span>&gt;</span>*<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">on:click</span>=<span class="hljs-string">{select(0)}</span>&gt;</span>0<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">on:click</span>=<span class="hljs-string">{select(</span>"<span class="hljs-attr">.</span>")}&gt;</span>.<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">on:click</span>=<span class="hljs-string">{clear}</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"clear"</span>&gt;</span>C<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"operator"</span>&gt;</span>/<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"equals"</span> &gt;</span>=<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>

...
</code></pre>
<p>Svelte <code>on:click</code> directive allows you attach an event handler to an element, so that when you call the <code>select</code> function for an element, it displays the number of that element appended to the previous value.</p>
<p>The <code>clear</code> button also has the event handler clear, to clear the screen and reset to <code>""</code> anytime it's called.</p>
<p>If you get everything right, you should see the value of the buttons clicked on the screen.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/08/image-126.png" alt="Image showing the numbers displaying on the screen when clicked." width="600" height="400" loading="lazy"></p>
<p>Let's create an event handler to perform an addition function and display the result. This will serve as the basis for all other operations in the calculator.</p>
<p>Update the <code>&lt;script&gt;&lt;/script&gt;</code> tag as follows:</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">script</span>&gt;</span><span class="javascript">
    ...
    let operand;
    <span class="hljs-keyword">let</span> result;

    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">addition</span>(<span class="hljs-params"></span>) </span>{
        operand = <span class="hljs-built_in">Number</span>(display_number);
        display_number = <span class="hljs-string">""</span>;
    }

    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">equals</span>(<span class="hljs-params"></span>) </span>{
        display_number = <span class="hljs-built_in">Number</span>(display_number);
        result = operand + display_number
        display_number = result.toString()
    }
</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
...
...
</code></pre>
<p>When performing calculations, you can have two or more operands – <code>operand</code> is the variable where the previous operand is stored, while <code>display_number</code> contains the current operand.</p>
<p><code>result</code> is the final result after performing an arithmetic operation.</p>
<p>The <code>addition</code> function takes the initial value displayed, converts it to a <code>Number</code> and stores it in the new variable <code>operand</code>, which resets <code>display_number</code> to its initial value <code>""</code>.</p>
<p>The <code>equals</code> function takes the new currently displayed number, adds it to <code>operand</code> and saves it as the final <code>result</code>. <code>result</code> is now converted to a <code>string</code> and saved as <code>display_number</code> so it appears on the screen.</p>
<p>Note that the <code>equals</code> function converts <code>result</code> to a string. When you want to use it for another calculation, the <code>addition</code> function will handle the conversion to a <code>Number</code>.</p>
<p>Try performing an addition operation to see if you got it right.</p>
<p>By now, <code>App.svelte</code> should look like this:</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">script</span>&gt;</span><span class="javascript">
    <span class="hljs-keyword">let</span> display_number = <span class="hljs-string">""</span>;
    <span class="hljs-keyword">const</span> select = <span class="hljs-function">(<span class="hljs-params">num</span>) =&gt;</span> <span class="hljs-function">() =&gt;</span> (display_number += num);
    <span class="hljs-keyword">const</span> clear = <span class="hljs-function">() =&gt;</span> (display_number = <span class="hljs-string">""</span>);

    <span class="hljs-keyword">let</span> operand;
    <span class="hljs-keyword">let</span> result;

    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">addition</span>(<span class="hljs-params"></span>) </span>{
            operand = <span class="hljs-built_in">Number</span>(display_number);
            display_number = <span class="hljs-string">""</span>;
      }

    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">equals</span>(<span class="hljs-params"></span>) </span>{
            display_number = <span class="hljs-built_in">Number</span>(display_number);
            result = operand + display_number
            display_number = result.toString()
      }
</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>

<span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"calculator"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"display"</span>&gt;</span>{display_number}<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"buttons"</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">on:click</span>=<span class="hljs-string">{select(7)}</span>&gt;</span>7<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">on:click</span>=<span class="hljs-string">{select(8)}</span>&gt;</span>8<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">on:click</span>=<span class="hljs-string">{select(9)}</span>&gt;</span>9<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">on:click</span>=<span class="hljs-string">{addition}</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"operator"</span> &gt;</span>+<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">on:click</span>=<span class="hljs-string">{select(4)}</span>&gt;</span>4<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">on:click</span>=<span class="hljs-string">{select(5)}</span>&gt;</span>5<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">on:click</span>=<span class="hljs-string">{select(6)}</span>&gt;</span>6<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"operator"</span> &gt;</span>-<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">on:click</span>=<span class="hljs-string">{select(1)}</span>&gt;</span>1<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">on:click</span>=<span class="hljs-string">{select(2)}</span>&gt;</span>2<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">on:click</span>=<span class="hljs-string">{select(3)}</span>&gt;</span>3<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"operator"</span>&gt;</span>*<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">on:click</span>=<span class="hljs-string">{select(0)}</span>&gt;</span>0<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">on:click</span>=<span class="hljs-string">{select(</span>"<span class="hljs-attr">.</span>")}&gt;</span>.<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">on:click</span>=<span class="hljs-string">{clear}</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"clear"</span>&gt;</span>C<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"operator"</span>&gt;</span>/<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">on:click</span>=<span class="hljs-string">{equals}</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"equals"</span> &gt;</span>=<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>

<span class="hljs-tag">&lt;<span class="hljs-name">style</span>&gt;</span><span class="css">
<span class="hljs-selector-class">.calculator</span> {
    <span class="hljs-attribute">display</span>: inline-block;
    <span class="hljs-attribute">border</span>: <span class="hljs-number">1px</span> solid <span class="hljs-number">#ccc</span>;
    <span class="hljs-attribute">padding</span>: <span class="hljs-number">10px</span>;
    <span class="hljs-attribute">border-radius</span>: <span class="hljs-number">5px</span>;
    <span class="hljs-attribute">box-shadow</span>: <span class="hljs-number">0</span> <span class="hljs-number">2px</span> <span class="hljs-number">5px</span> <span class="hljs-built_in">rgba</span>(<span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0.1</span>);
}

<span class="hljs-selector-class">.display</span> {
    <span class="hljs-attribute">font-size</span>: <span class="hljs-number">24px</span>;
    <span class="hljs-attribute">border</span>: <span class="hljs-number">1px</span> solid <span class="hljs-number">#ccc</span>;
    <span class="hljs-attribute">height</span>: <span class="hljs-number">24px</span>;
    <span class="hljs-attribute">padding</span>: <span class="hljs-number">10px</span>;
    <span class="hljs-attribute">margin-bottom</span>: <span class="hljs-number">10px</span>;
    <span class="hljs-attribute">width</span>: <span class="hljs-number">300px</span>;
    <span class="hljs-attribute">text-align</span>: right;
}
<span class="hljs-selector-class">.buttons</span> {
    <span class="hljs-attribute">display</span>: grid;
    <span class="hljs-attribute">grid-template-columns</span>: <span class="hljs-built_in">repeat</span>(<span class="hljs-number">4</span>, <span class="hljs-number">75px</span>);
    <span class="hljs-attribute">gap</span>: <span class="hljs-number">5px</span>;
}

<span class="hljs-selector-tag">button</span> {
    <span class="hljs-attribute">padding</span>: <span class="hljs-number">10px</span>;
    <span class="hljs-attribute">font-size</span>: <span class="hljs-number">18px</span>;
    <span class="hljs-attribute">border</span>: none;
    <span class="hljs-attribute">cursor</span>: pointer;
    <span class="hljs-attribute">border-radius</span>: <span class="hljs-number">5px</span>;
    <span class="hljs-attribute">font-family</span>: Arial, sans-serif;
    <span class="hljs-attribute">text-align</span>: center;
}
<span class="hljs-selector-class">.operator</span>{
    <span class="hljs-attribute">border</span>: <span class="hljs-number">0px</span> solid <span class="hljs-number">#A46D19</span>;
    <span class="hljs-attribute">background</span>: <span class="hljs-number">#F90</span>;
}
<span class="hljs-selector-class">.clear</span>{
    <span class="hljs-attribute">border</span>: <span class="hljs-number">0px</span> solid <span class="hljs-number">#000</span>;
    <span class="hljs-attribute">background</span>: red;
}
<span class="hljs-selector-class">.equals</span>{
    <span class="hljs-attribute">border</span>: <span class="hljs-number">0px</span> solid <span class="hljs-number">#000</span>;
    <span class="hljs-attribute">background</span>: <span class="hljs-number">#245BE9</span>;
    <span class="hljs-attribute">width</span>: <span class="hljs-number">320px</span>
}
<span class="hljs-selector-class">.operator</span><span class="hljs-selector-pseudo">:hover</span>{
    <span class="hljs-attribute">background</span>: <span class="hljs-number">#FFD700</span>;
}
<span class="hljs-selector-class">.clear</span><span class="hljs-selector-pseudo">:hover</span> {
    <span class="hljs-attribute">background</span>: <span class="hljs-number">#FFC0CB</span> ;
}
<span class="hljs-selector-class">.equals</span><span class="hljs-selector-pseudo">:hover</span> {
    <span class="hljs-attribute">background</span>: <span class="hljs-number">#ADD8E6</span>; 
}
</span><span class="hljs-tag">&lt;/<span class="hljs-name">style</span>&gt;</span>
</code></pre>
<p>Let's improve the code to support other operations – subtraction, multiplication and division:</p>
<pre><code class="lang-javascript">&lt;script&gt;
...
let operator;
<span class="hljs-keyword">let</span> operators = [<span class="hljs-string">"+"</span>, <span class="hljs-string">"-"</span>, <span class="hljs-string">"*"</span>, <span class="hljs-string">"/"</span>];

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">operation</span>(<span class="hljs-params">sign</span>) </span>{
        operand = <span class="hljs-built_in">Number</span>(display_number);
        operator = sign;
        display_number = <span class="hljs-string">""</span>;
  }

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">equals</span>(<span class="hljs-params"></span>) </span>{
    display_number = <span class="hljs-built_in">Number</span>(display_number);
    <span class="hljs-keyword">if</span> (operator === <span class="hljs-string">"+"</span>) {
      result = operand + display_number;
    } <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (operator === <span class="hljs-string">"-"</span>) {
      result = operand - display_number;
    } <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (operator === <span class="hljs-string">"*"</span>) {
      result = operand * display_number;
    } <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (operator === <span class="hljs-string">"/"</span>) {
      result = operand / display_number;
    }
display_number = result.toString()
&lt;/script&gt;
...
...
</code></pre>
<p>The <code>addition</code> function changes to <code>operation</code>, which supports the <code>sign</code> argument.</p>
<p>The <code>equals</code> function performs operations based on the value of the sign argument in the function operation.</p>
<p>Update the HTML code to add event handlers to the various arithmetic operations:</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"calculator"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"display"</span>&gt;</span>{display_number}<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"buttons"</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">on:click</span>=<span class="hljs-string">{select(7)}</span>&gt;</span>7<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">on:click</span>=<span class="hljs-string">{select(8)}</span>&gt;</span>8<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">on:click</span>=<span class="hljs-string">{select(9)}</span>&gt;</span>9<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">on:click</span>=<span class="hljs-string">{()</span> =&gt;</span> operation(operators[0])} class="operator" &gt;+<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">on:click</span>=<span class="hljs-string">{select(4)}</span>&gt;</span>4<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">on:click</span>=<span class="hljs-string">{select(5)}</span>&gt;</span>5<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">on:click</span>=<span class="hljs-string">{select(6)}</span>&gt;</span>6<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">on:click</span>=<span class="hljs-string">{()</span> =&gt;</span> operation(operators[1])} class="operator" &gt;-<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">on:click</span>=<span class="hljs-string">{select(1)}</span>&gt;</span>1<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">on:click</span>=<span class="hljs-string">{select(2)}</span>&gt;</span>2<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">on:click</span>=<span class="hljs-string">{select(3)}</span>&gt;</span>3<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">on:click</span>=<span class="hljs-string">{()</span> =&gt;</span> operation(operators[2])} class="operator"&gt;*<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">on:click</span>=<span class="hljs-string">{select(0)}</span>&gt;</span>0<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">on:click</span>=<span class="hljs-string">{select(</span>"<span class="hljs-attr">.</span>")}&gt;</span>.<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">on:click</span>=<span class="hljs-string">{clear}</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"clear"</span>&gt;</span>C<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">on:click</span>=<span class="hljs-string">{()</span> =&gt;</span> operation(operators[3])} class="operator"&gt;/<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">on:click</span>=<span class="hljs-string">{equals}</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"equals"</span> &gt;</span>=<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
</code></pre>
<p>Each function takes its sign value by accessing the respective sign in <code>operator</code>s.</p>
<p>We now have a working calculator.</p>
<p>Now, how do we handle something like this?</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/08/image-144.png" alt="The image shows the numbers going out of the display borders" width="600" height="400" loading="lazy"></p>
<p>The above is a bug where the numbers exceed the display boundaries.</p>
<p>To solve this error, update the <code>display</code> div as follows:</p>
<pre><code class="lang-html">...
<span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"calculator"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"display"</span>&gt;</span>{display_number.length <span class="hljs-tag">&lt; <span class="hljs-attr">23</span>? <span class="hljs-attr">display_number:</span> <span class="hljs-attr">display_number.substring</span>(<span class="hljs-attr">0</span>,<span class="hljs-attr">23</span>)}&lt;/<span class="hljs-attr">div</span>&gt;</span>
    ...
<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
...
</code></pre>
<p>If the length of <code>display_number</code> is greater than <code>22</code>, which is the number of digits the display screen can contain, the first twenty-two characters is selected.</p>
<p>This will fix the above bug.</p>
<h2 id="heading-challenge">Challenge</h2>
<p>You can further extend the calculator by:</p>
<ul>
<li><p>Adding advanced mathematical and scientific operations.</p>
</li>
<li><p>Giving room for users to use their keyboard to input values.</p>
</li>
<li><p>Displaying the arithmetic operations on screen, before calculating.</p>
</li>
</ul>
<h2 id="heading-conclusion">Conclusion</h2>
<p>In this tutorial, you have learned how to use Svelte to create interactivity in a web app. And you also learned about Svelte event handlers.</p>
<p>You can further your current Svelte knowledge by visiting the official <a target="_blank" href="https://svelte.dev/docs/introduction">documentation</a>.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Build a WhatsApp Dictionary Chatbot using Twilio, FastAPI, and MongoDB ]]>
                </title>
                <description>
                    <![CDATA[ Sometimes you want to check what a word means while chatting with someone in WhatsApp. But you don't want to exit or minimize the app. Well, how about building a WhatsApp bot that can give you the meaning of words you want to know? In this tutorial, ... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-build-a-whatsapp-dictionary-chatbot-using-twilio-fast-api-and-mongodb/</link>
                <guid isPermaLink="false">66d45d5a3a8352b6c5a2a9ed</guid>
                
                    <category>
                        <![CDATA[ #chatbots ]]>
                    </category>
                
                    <category>
                        <![CDATA[ MongoDB ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Adejumo Ridwan Suleiman ]]>
                </dc:creator>
                <pubDate>Wed, 02 Aug 2023 23:47:11 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2023/08/WHATSAPP-DICTIONARY-CHATBOT.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Sometimes you want to check what a word means while chatting with someone in WhatsApp. But you don't want to exit or minimize the app.</p>
<p>Well, how about building a WhatsApp bot that can give you the meaning of words you want to know?</p>
<p>In this tutorial, you will learn how to build a chatbot that can serve as your dictionary. It'll be easily accessible on WhatsApp using the Twilio MessagingX WhatsApp API to send and receive messages. We'll use Fast API to create the web server and interact with the database, and MongoDB to store the words and their meanings into a database.</p>
<p>By the end of this tutorial, you will have developed a functional chatbot that can define words in real-time while you're conversing on WhatsApp.</p>
<h2 id="heading-prerequisites">Prerequisites</h2>
<ul>
<li><p>Python 3.9+ installed on your machine.</p>
</li>
<li><p>MongoDB free account – if you don’t have one, you can set it up <a target="_blank" href="https://www.mongodb.com/cloud/atlas/lp/try4?utm_ad_campaign_id=12212624539&amp;adgroup=115749718303&amp;cq_cmp=12212624539&amp;gad=1">here</a>.</p>
</li>
<li><p>Twilio free account – you can set up one <a target="_blank" href="https://www.twilio.com/en-us">here</a>.</p>
</li>
<li><p>Merriam-Webster Developer’s account – you can set up one <a target="_blank" href="https://www.dictionaryapi.com/register/index">here</a>.</p>
</li>
<li><p>An IDE or text editor, such as <a target="_blank" href="https://code.visualstudio.com/">VS code</a>.</p>
</li>
</ul>
<h2 id="heading-set-up-your-development-environment">Set Up Your Development Environment</h2>
<p>Before you start, you need to set up your development environment by creating the required directory and files. Here's the commands for that:</p>
<pre><code class="lang-shell">mkdir whatsappDictionary
cd whatsappDictionary
touch requirements.txt models.py utils.py main.py .env
</code></pre>
<ul>
<li><p><code>requirements.txt</code> contains the required libraries to get the chatbot up and running.</p>
</li>
<li><p><code>model.py</code> contains the code connecting your chatbot to the MongoDB server</p>
</li>
<li><p><code>utils.py</code> includes the code to connect to Twilio MessagingX WhatsApp API</p>
</li>
<li><p><code>main.py</code> contains the code to build the Fast API server and connect to the Merriam-Webster API.</p>
</li>
<li><p><code>whatsappDictionary</code> is the directory for all the files.</p>
</li>
</ul>
<p>Next, you'll create and activate a virtual environment and update the Python package manager <code>pip</code> to the most recent version using the following command:</p>
<pre><code class="lang-shell">python -m venv venv; ./venv/Scripts/Activate; pip --upgrade pip
</code></pre>
<p>If you are on a Linux machine, use this command:</p>
<pre><code class="lang-shell">pyton -m venv venv; venv\\Scripts\\activate.bat; pip --upgrade pip
</code></pre>
<p>To learn more about virtual environments and their benefits, you can read this <a target="_blank" href="https://linuxhostsupport.com/blog/why-using-a-python-virtual-environment-is-a-good-choice/#:~:text=Virtual%20environments%20are%20of%20great,the%20help%20of%20virtual%20environments.">tutorial</a>.</p>
<p>Next you'll need to populate the <code>requirements.txt</code> file with the following dependencies:</p>
<pre><code class="lang-text">fastapi
uvicorn
twilio
pymongo
pyngrok
requests
dotenv
</code></pre>
<ul>
<li><p><code>fastapi</code> is a Python framework for building APIs quickly and easily</p>
</li>
<li><p><code>uvicorn</code> is a lightning-fast server implementation for Python</p>
</li>
<li><p><code>twilio</code> allows you to interact with the Twilio MessagingX WhatsApp API</p>
</li>
<li><p><code>pymongo</code> is the driver you will use to connect to the MongoDB server</p>
</li>
<li><p><code>pyngrok</code> enables you to tunnel a local server to a public URL</p>
</li>
<li><p><code>requests</code> allow you to send HTTP requests using Python</p>
</li>
<li><p><code>dotenv</code> loads the environment variables from the <em>.env</em> file.</p>
</li>
</ul>
<p>Install these dependencies by running the following command on your terminal:</p>
<pre><code class="lang-shell">pip install -r requirements.txt
</code></pre>
<h2 id="heading-configure-the-database">Configure the Database</h2>
<p>You now want to set up a database to store words and their definitions. You are going to use MongoDB, which is a NoSQL language and is easy to set up.</p>
<p>You will need to create a free account on the MongoDB website (if you don't have one already). Once you have an account, log in to create a new <strong>Shared</strong> cluster and database.</p>
<p><img src="https://lh5.googleusercontent.com/Oz_BdWfzS5wphrYXi_WzAX_2e-2rzHPp3wqlTeH4BXP5HSU73Scnt39qO85Ao9TstyzYKjHYnjXXO1qabp43jJF0W6vcGkhQ3mkt6ZHn-OvurIJKAv1WYOYBxmklS0_zw775g51X5xhc3js92qNe7mUErBpnKooWtvzl7AMK6TzAO8X6qwSbbK2lRWeBNQ" alt="This image shows you how to create a shared cluster on MongoDB" width="600" height="400" loading="lazy"></p>
<p><em>Image showing how to create a shared cluster on Mongo DB</em></p>
<p>Afterwards, go to <strong>Security_,_</strong> then <strong>ADD NEW DATABASE USER</strong> to add a new user with read/write access to the database.</p>
<p><img src="https://lh3.googleusercontent.com/r0HxaAqOZZn8yIV3ObgfuAojNdkGefNzjPJM4DVRRlPCTIpl9NmvGr-lY0hjLGWlNnyRuHQF34ujKGV2H_F4BjS746TLOfljbMax24kFo9haf0gxa9f2ZQzG-DVxI7qqzQx4W_YuZhh7y7ENSqCgOH60EWAi6hiDYO9_GilZut2uJPgy7aYMaTOd-uQTRg" alt="This image shows the tab where you can add a new database" width="600" height="400" loading="lazy"></p>
<p><em>This image shows the tab where you can add a new database</em></p>
<p><img src="https://lh6.googleusercontent.com/iOOmBGx8NfOkCeZ_ioNqLN0aRKoJMs9RWKaRgd1xiex6WnzekwpuKLlSpj963PvfKTRTI7ZZ9pzGIFn_rJ5mFm7rrIodPTTZ1jpdnUEqj4drCOpcQ6ZWb5k6R2azZ5BCBA_zsY_ee5OtJ8m4roU0SHNRFoeXYKMu2yKKLOxpnPoEYBJKpfIavRP5-KBA3A" alt="This image shows the window of adding a new database user" width="600" height="400" loading="lazy"></p>
<p><em>This image shows the window of adding a new database user</em></p>
<p>Go back to the cluster dashboard, click on <strong>Connect</strong> and then on <strong>Drivers</strong>.</p>
<p><img src="https://lh4.googleusercontent.com/EOqNVq2nqObKtABzLQphGDWRFgXPFybQhm11R_XPWdlqgigbzVsMA1zaj2zVjjMjlHpdzauXpfjofw1cyE_RUc2ijI8h_qDLN10sSoMeCGUuGU1DZ3tGB4IqRRkJmgUhNGxDhUX3Zljgo1SSgdLZwWreqFHXpEJ2WuPE62QamlRAop6JtVOfARJbWU4UIg" alt="This image shows you the final process while trying to connect to the cluster" width="600" height="400" loading="lazy"></p>
<p><em>This image shows you the final process while trying to connect to the cluster</em></p>
<p>Copy the code shown to you into <code>model.py</code>:</p>
<p><img src="https://lh4.googleusercontent.com/s1M_HQA6uAKPxE6jZtyzh4iLHtk_4m-nIv9IOW9D0igHKEKMrwZjNAAsVIwKOzqCAhNQM-qIimO4pFbKqSAUKh78VJ9ZC02pIP5uCBT7ndw0k-6nte3CLay481osRVkDwDoMkCLaSx4ydTWDRBndVVDVHWIUFEhBjaeWoOkvZVS6SImAnjJ3BTHnT2yIMQ" alt="This image shows the code on how to connect to the MongoDB server using the pymongo driver." width="600" height="400" loading="lazy"></p>
<p><em>This image shows the code on how to connect to the MongoDB server using the pymongo driver.</em></p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> pymongo.mongo_client <span class="hljs-keyword">import</span> MongoClient
<span class="hljs-keyword">from</span> pymongo.server_api <span class="hljs-keyword">import</span> ServerApi

uri = <span class="hljs-string">f"mongodb+srv://adejumoridwan:&lt;password&gt;@cluster0.d9jr4ev.mongodb.net/?retryWrites=true&amp;w=majority"</span>

<span class="hljs-comment"># Send a ping to confirm a successful connection</span>
<span class="hljs-keyword">try</span>:
    client.admin.command(<span class="hljs-string">'ping'</span>)
    print(<span class="hljs-string">"Pinged your deployment. You successfully connected to MongoDB!"</span>)
<span class="hljs-keyword">except</span> Exception <span class="hljs-keyword">as</span> e:
    print(e)
</code></pre>
<p>Give your password to run the code and connect to the MongoDB server. You don’t want anyone to see this. Go to the <code>.env</code> file you created and store your password there.</p>
<pre><code class="lang-text">MONGO_SECRET=&lt;password&gt;
</code></pre>
<p>Next, update <code>model.py</code> to access the <code>.env</code> file.</p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> pymongo.mongo_client <span class="hljs-keyword">import</span> MongoClient
<span class="hljs-keyword">from</span> pymongo.server_api <span class="hljs-keyword">import</span> ServerApi
<span class="hljs-keyword">from</span> dotenv <span class="hljs-keyword">import</span> load_dotenv
<span class="hljs-keyword">import</span> os

load_dotenv()
password = os.environ.get(<span class="hljs-string">'MONGO_SECRET'</span>)

uri = <span class="hljs-string">f"mongodb+srv://adejumoridwan:<span class="hljs-subst">{password}</span>@cluster0.d9jr4ev.mongodb.net/?retryWrites=true&amp;w=majority"</span>

<span class="hljs-comment"># Send a ping to confirm a successful connection</span>
<span class="hljs-keyword">try</span>:
    client.admin.command(<span class="hljs-string">'ping'</span>)
    print(<span class="hljs-string">"Pinged your deployment. You successfully connected to MongoDB!"</span>)
<span class="hljs-keyword">except</span> Exception <span class="hljs-keyword">as</span> e:
    print(e)
</code></pre>
<ul>
<li><p><code>load_dotenv()</code> loads the variables in .env</p>
</li>
<li><p><code>os.environ.get('MONGO_SECRET')</code> receives the password from .env, which stores the variable password</p>
</li>
</ul>
<p>Run the script to connect to the MongoDB server. You can create a collection by clicking on your Cluster name and going to Collections. Collections are NoSQL versions of SQL tables.</p>
<p>Click on <strong>Create Database</strong> to create your database:</p>
<p><img src="https://lh6.googleusercontent.com/yrP5_ej7jaGl3mQH9uXQEkmubLt-50NOiDcd6XG_8bV3yWe-cJZnA6snsN_xoJqpp7XQDFpXMk4xVQZHuY23D4fscJbYJfSExfDzWoeiEOQIXBjosDRchgJPu7ZWtCilXdQg5nuKBmaE10hh_Ht-zAkuGFn-RUoTwuIiH8xY2FCXXKi4TW8T3NyJEo6LyQ" alt="This shows information and tabs regarding the created clusters such as Overview, Collections and so on
" width="600" height="400" loading="lazy"></p>
<p><em>This shows information and tabs regarding the created clusters such as Overview, Collections and so on</em></p>
<p>Give the database and collection names. The database and collection names for this tutorial are <strong>MY_DB</strong> and <strong>dictionary</strong>, respectively.</p>
<p><img src="https://lh4.googleusercontent.com/HdO8oJJXmQhD1n6XeiZdP0qicncdy5U7pyraNu3zX0xi2Qpu7j1JbN_ZmV8FVK4CZu8XHoCAE4wNIwEXu5J0e3ltvITtMjZ7GzI7XxwCPE7UyFnNAlJc9ycRNfmWCNeZiIXBe4hNlf7_F9HvejXz1CKQ644WvgGRFXMBvKqqG3pqM9iBMZHZStS8p93ROA" alt="The window shows you the option to fill in when you want to create a database, such as a database name, collection name, and additional preferences." width="600" height="400" loading="lazy"></p>
<p><em>The window shows you the option to fill in when you want to create a database, such as a database name, collection name, and additional preferences.</em></p>
<p>Go to <code>models.py</code> and update the code to create a new client and connect to the server.</p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> pymongo.mongo_client <span class="hljs-keyword">import</span> MongoClient
<span class="hljs-keyword">from</span> pymongo.server_api <span class="hljs-keyword">import</span> ServerApi
<span class="hljs-keyword">from</span> dotenv <span class="hljs-keyword">import</span> load_dotenv
<span class="hljs-keyword">import</span> os

load_dotenv()
password = os.environ.get(<span class="hljs-string">'MONGO_SECRET'</span>)

uri = <span class="hljs-string">f"mongodb+srv://adejumoridwan:<span class="hljs-subst">{password}</span>@cluster0.d9jr4ev.mongodb.net/?retryWrites=true&amp;w=majority"</span>

<span class="hljs-comment"># Create a new client and connect to the server</span>
client = MongoClient(uri, server_api=ServerApi(<span class="hljs-string">'1'</span>))

dictionary_collection = client[<span class="hljs-string">"MY_DB"</span>][<span class="hljs-string">"dictionary"</span>]

<span class="hljs-comment"># Send a ping to confirm a successful connection</span>
<span class="hljs-keyword">try</span>:
    client.admin.command(<span class="hljs-string">'ping'</span>)
    print(<span class="hljs-string">"Pinged your deployment. You successfully connected to MongoDB!"</span>)
<span class="hljs-keyword">except</span> Exception <span class="hljs-keyword">as</span> e:
    print(e)
</code></pre>
<p><code>dictionary_collection</code> is what you will use to update entries into the server later.</p>
<h2 id="heading-how-to-configure-twilio-sandbox-for-whatsapp">How to Configure Twilio Sandbox for WhatsApp</h2>
<p>To configure the Twilio sandbox for WhatsApp, go to Twilio Console. Under Develop, click on Messaging, then Try it out. Under Try it out, click on Send a WhatsApp Message.</p>
<p><img src="https://lh6.googleusercontent.com/QTLWWiK_pb8FYHgyeXucP7r5WB1YpgGpBsC-spLRJWjTsT5rMkmREk7rVwT9aawQFMd-ZxCt1nLfjk57EzA2XfEmFPKSzsZYM9NVFr3XQLwDwCN9m7am7BTSEEFZUOQFSV2BQY82wgNVSCTWZD4DHV7JLo1r3mx49NXJO6eQsG0BxcM62fx-I101wjX9oA" alt="This sandbox allows you to send WhatsApp messages to your number" width="600" height="400" loading="lazy"></p>
<p><em>This sandbox allows you to send WhatsApp messages to your number</em></p>
<p>To connect to the WhatsApp Sandbox, save the number provided on the sandbox on your device and send the message join manner-free to the number, or you can scan the QR code on your device.</p>
<p><img src="https://lh6.googleusercontent.com/k1L4We_5SE5PH8ASRHfrocoEizzY0eKSOnHUEvGi-qD41nowBJtxLEDk6amQboYi59SKxYdW32PC1G74Rj2uP4qo3aLU-GTbThlEnHgj9bUStP5K9_kBVNX5ZkCcAadQZDS1YYtchfIpGCrtWlyVo2UjjXZeIFCYI7UU4HxSDmicSCjZR_l1u9ViUS8eqg" alt="Here you see the sandbox to connect to whatsapp sandbox to your number
" width="600" height="400" loading="lazy"></p>
<p><em>Here you see the sandbox to connect to whatsapp sandbox to your number</em></p>
<p>Once the connection is successful, copy the code and paste it into the file <code>utils.py</code>:</p>
<p><img src="https://lh5.googleusercontent.com/0exaxbIgwJQYtD4kKeqcWnAlUy0bmCyap4f4pvGF8txH_meTEmckcEggzLwjL0dGszckstN8whxkYY9iz2EqXTxHfcxO6mfF_wt70NDbGqZVB56lZNZJBEi_Gv9Ee_OVTFF91czWx3AgedQKY5uhim16saPGYcbXTbknc4IL0lMQ0VDHODGJJfE8vjCJFA" alt="Here you can see how to connect to WhatsApp API in various languages. Currently, the image is showing how to connect to WhatsApp API so that you can send messages from Twilio." width="600" height="400" loading="lazy"></p>
<p><em>Here you can see how to connect to WhatsApp API in various languages. Currently, the image is showing how to connect to WhatsApp API so that you can send messages from Twilio.</em></p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> twilio.rest <span class="hljs-keyword">import</span> Client

account_sid = <span class="hljs-string">'&lt;account_sid&gt;'</span>
auth_token = <span class="hljs-string">'[AuthToken]'</span>
client = Client(account_sid, auth_token)

message = client.messages.create(
  from_=<span class="hljs-string">'whatsapp:+14155238886'</span>,
  body=<span class="hljs-string">'Your appointment is coming up on July 21 at 3PM'</span>,
  to=<span class="hljs-string">'whatsapp:&lt;to_number&gt;
)

print(message.sid)</span>
</code></pre>
<p>The <code>client.messages.create()</code> function allows you to send messages to your WhatsApp from the WhatsApp sandbox. It takes three parameters:</p>
<ul>
<li><p><code>from_</code> is where the message is coming from, that is, from the WhatsApp Sandbox</p>
</li>
<li><p><code>body</code> takes in the body of your message</p>
</li>
<li><p><code>to</code> is the WhatsApp number you are sending to</p>
</li>
</ul>
<h2 id="heading-how-to-connect-to-the-twilio-api">How to Connect to the Twilio API</h2>
<p>Go to the .env file to store your Twilio authentication token, account SID, Twilio sandbox number, and WhatsApp number.</p>
<pre><code class="lang-text">MONGO_SECRET="&lt;password&gt;"
TWILIO_ACCOUNT_SID="&lt;account_sid&gt;"
TWILIO_AUTH_TOKEN="&lt;auth_token&gt;"
TWILIO_NUMBER="&lt;twilio_number&gt;"
TO_NUMBER="&lt;to_number&gt;"
</code></pre>
<p>Update the <code>utils.py</code> file to access these variables:</p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> twilio.rest <span class="hljs-keyword">import</span> Client
<span class="hljs-keyword">from</span> dotenv <span class="hljs-keyword">import</span> load_dotenv
<span class="hljs-keyword">import</span> os

load_dotenv()

account_sid = os.getenv(<span class="hljs-string">"TWILIO_ACCOUNT_SID"</span>)
auth_token = os.getenv(<span class="hljs-string">"TWILIO_AUTH_TOKEN"</span>)
client = Client(account_sid, auth_token)
twilio_number = os.getenv(<span class="hljs-string">'TWILIO_NUMBER'</span>)
to_number = os.getenv(“TO_NUMBER”)

message = client.messages.create(
  from_=<span class="hljs-string">f'whatsapp:<span class="hljs-subst">{twilio_number}</span>'</span>,
  body=<span class="hljs-string">'Your appointment is coming up on July 21 at 3PM'</span>,
  to=<span class="hljs-string">f'whatsapp:<span class="hljs-subst">{to_number}</span>
)</span>
</code></pre>
<p><code>load_dotenv()</code> loads the environment variables, and <code>os.getenv</code> gets these variables from the environment.</p>
<p>Next is to define a <code>send_message</code> function. This function is going to have two arguments: <code>to_number</code> and <code>text</code>. The function will send a message defined in <code>text</code> to <code>to_number</code>.</p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> twilio.rest <span class="hljs-keyword">import</span> Client
<span class="hljs-keyword">from</span> dotenv <span class="hljs-keyword">import</span> load_dotenv
<span class="hljs-keyword">import</span> os

load_dotenv()

account_sid = os.getenv(<span class="hljs-string">"TWILIO_ACCOUNT_SID"</span>)
auth_token = os.getenv(<span class="hljs-string">"TWILIO_AUTH_TOKEN"</span>)
client = Client(account_sid, auth_token)
twilio_number = os.getenv(<span class="hljs-string">'TWILIO_NUMBER'</span>)

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">send_message</span>(<span class="hljs-params">to_number, text</span>):</span>
      message = client.messages.create(
          from_=<span class="hljs-string">f"whatsapp:<span class="hljs-subst">{twilio_number}</span>"</span>,
          body=text,
          to=<span class="hljs-string">f"whatsapp:<span class="hljs-subst">{to_number}</span>"</span>
          )
</code></pre>
<p>Update the <code>send_message</code> function to configure logging in case errors are encountered when sending messages.</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> logging
<span class="hljs-keyword">from</span> dotenv <span class="hljs-keyword">import</span> load_dotenv
<span class="hljs-keyword">import</span> os
<span class="hljs-keyword">from</span> twilio.rest <span class="hljs-keyword">import</span> Client

load_dotenv()

account_sid = os.getenv(<span class="hljs-string">"TWILIO_ACCOUNT_SID"</span>)
auth_token = os.getenv(<span class="hljs-string">"TWILIO_AUTH_TOKEN"</span>)
client = Client(account_sid, auth_token)
twilio_number = os.getenv(<span class="hljs-string">'TWILIO_NUMBER'</span>)

<span class="hljs-comment"># Set up logging</span>
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)

<span class="hljs-comment"># Sending message logic through Twilio Messaging API</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">send_message</span>(<span class="hljs-params">to_number, text</span>):</span>
    <span class="hljs-keyword">try</span>:
        message = client.messages.create(
            from_=<span class="hljs-string">f"whatsapp:<span class="hljs-subst">{twilio_number}</span>"</span>,
            body=text,
            to=<span class="hljs-string">f"whatsapp:<span class="hljs-subst">{to_number}</span>"</span>
            )
        logger.info(<span class="hljs-string">f"Message sent to <span class="hljs-subst">{to_number}</span>: <span class="hljs-subst">{message.body}</span>"</span>)
    <span class="hljs-keyword">except</span> Exception <span class="hljs-keyword">as</span> e:
        logger.error(<span class="hljs-string">f"Error sending message to <span class="hljs-subst">{to_number}</span>: <span class="hljs-subst">{e}</span>"</span>)
</code></pre>
<h2 id="heading-how-to-build-the-fastapi-backend">How to Build the FastAPI Backend</h2>
<p>Inside the <code>main.py</code>, set up a basic FastAPI application.</p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> fastapi <span class="hljs-keyword">import</span> FastAPI

app = FastAPI()

<span class="hljs-meta">@app.get("/")</span>
<span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">index</span>():</span>
    <span class="hljs-keyword">return</span> {<span class="hljs-string">"message"</span>: <span class="hljs-string">"I love FreeCodeCamp"</span>}
</code></pre>
<p>The code below sets up a basic FastAPI backend, creating a new instance of the <code>FastAPI</code> class and assigning it to the app variable.</p>
<p>The <code>@app.get</code> decorator creates a new endpoint that you can access with an HTTP GET request. The endpoint is at the root URL <code>/</code> and returns a JSON response with a single key-value pair: <code>"message": "I love FreeCodeCamp"</code>.</p>
<p>To run the app, run the following command in your terminal:</p>
<pre><code class="lang-shell">uvicorn main:app --reload
</code></pre>
<p>On your browser, open the host <code>http://127.0.0.1:8000</code>. You will see a JSON response of <code>{"message": "I love FreeCodeCamp"}</code>. You can also access an interactive API doc provided by swagger on the host <code>http://127.0.0.1:8000/doc</code> which allows you to interact with your API and see if you have any errors.</p>
<p><img src="https://lh3.googleusercontent.com/3WeI9jW_jeI0WMYhYrWjMUFsbwD6cAANv1DuYNkC2hhl2-HyBMQjEeX5SABC4GdbMyArs88-DkxdgTNES2ogHjFNBMqvNNFyUq3825kBxFGgazth3TWrMv72Qm_9kGs6atTFUSl6NnjeYkdaxHlV7XqFg8JMK9v6t5Dq5rUCxKU7SHv-wZnBPpIy3U31ag" alt="This interactive documentation provided by swagger shows how to interact with your API to check for errors." width="600" height="400" loading="lazy"></p>
<p><em>This interactive documentation provided by swagger shows how to interact with your API to check for errors.</em></p>
<h2 id="heading-how-to-set-up-ngrok">How to Set Up ngrok</h2>
<p>To receive Twilio messages on the backend, you will use <code>ngrok</code> to host the local host on a public server. Read this <a target="_blank" href="https://www.twilio.com/blog/using-ngrok-2022#:~:text=Open%20a%20terminal%20window%20and,under%20your%20account%2C%20without%20restrictions.">post</a> to learn how to set up ngrok on your machine.</p>
<p>On ngrok administrator, run the command ngrok http 8000. This makes your host public, and you can receive messages on your backend.</p>
<p><img src="https://lh6.googleusercontent.com/6oErUtc-WBw1YBNLaw8yjfiMioLW7PpTmUWJY4Y6nrOJ3Q0iKC5fnN8YAvVxBWMYHO296TkMwo7NyKptqOWS_tv_ftUe1Mqetkoz57HCP_rzp3lrjgpvreSkJlPKPV-GA9kQVNbp2biQVSIg-l2uGKKVMFEGG-EHSl57fF_HqiOBE-iXP_4BwAwfHc7KIA" alt="Here you can see ngrok up and running on your local machine" width="600" height="400" loading="lazy"></p>
<p><em>Here you can see ngrok up and running on your local machine</em></p>
<p>Go to your WhatsApp Sandbox, under Sandbox settings, and paste the forwarding URL <code>https://b5a6-105-112-120-51.ngrok-free.app</code> appending it with <code>/message</code> under <strong>When a message comes in</strong> and click Save.</p>
<p><img src="https://lh6.googleusercontent.com/VejaBgdyh6Zf5bUCIQyyCZjTvQhWSpEadbP0FliUyOH64QC8fQn9P7wRDgElxo8h7_T7SuleXD01PAeH8hirp2Gn4CaCBDi7IDuIC8V5CfFsjzU-yKxL1_67rCQZ2H77IRpPr0R7P6IegfjyQ72JH-xAjEk0Y-RyckeBM7mFOaoRSrtjMBX3wHDJ1l3QZg" alt="This image shows how to configure your sandbox and link to the ngrok url" width="600" height="400" loading="lazy"></p>
<p><em>This image shows how to configure your sandbox and link to the ngrok url</em></p>
<h2 id="heading-how-to-connect-to-the-merriam-webster-api">How to Connect to the Merriam-Webster API</h2>
<p>To set up a Merriam-Webster dictionary account, <a target="_blank" href="https://www.dictionaryapi.com/register/index">go here</a> and fill out your credentials:</p>
<p><img src="https://lh4.googleusercontent.com/hQ5PhqXwHF1sVLOzsPIf5ehtM7VaGRwEwbA9l11HtIcZnhtkU0HAfR2R9dvXVl0lfmtO1ORIQwFUtNH3tl1Ck-S5e5AeGrHUU4Yq6IusrAKDI4iX4RI5u71whmBiw2jCH_cj0dolHjYjXxEVHInwrxFdH6qrbU3KGKRyKoC-rkEH2qv_DbUiBSCM-pviSg" alt="Image showing page to register for Merriam Webster Developer Center" width="600" height="400" loading="lazy"></p>
<p><em>Image showing page to register for Merriam Webster Developer Center</em></p>
<p>You can register for two keys: Collegiate Dictionary and Collegiate Thesaurus, though this tutorial uses only <strong>Collegiate Dictionary</strong>.</p>
<p><img src="https://lh3.googleusercontent.com/UUUGKxVa_DHx0yelDHCwFzX0uFj3K5tfp6nt4RczGAHnlj1UNZlRxjvXBAsS5_TMcbpnm2jYXWKed_Ek9vAM-qS544fS7mXJTAvdNXYH8tGih6bS7qXozWv5J4-52x1V9Cw1i76-MevLUiMwWuPmi_0EwzB-v2VyzV0kSpaun2Ok5TlmjqXAM6b-w84PvQ" alt="This shows the various keys one can apply for on Merriam-Webster" width="600" height="400" loading="lazy"></p>
<p><em>This shows the various keys one can apply for on Merriam-Webster</em></p>
<p>After filling in all your details, click on Register and Login.</p>
<p>In the home tab, go to Keys to get your API keys.</p>
<p><img src="https://lh6.googleusercontent.com/y_AGpxS8q4Pj-jscWFggBGDXgqE7amA7GygGPXknOtNTcATjdU716lvbIgHGOPo-cxIbdQ4q4RBfP8C4sXwGJlAw5SrpOH3uXf6rDCPh78jweyHYSYDyB_NSJ4SsYhnOqJWP788Yj3swTSUq2ostt2kHssn1KL3mFo3e-L_Y400-7amgsiWqHYfvbJZewA" alt="This key tab shows the keys you have registered for " width="600" height="400" loading="lazy"></p>
<p><em>This key tab shows the keys you have registered for</em></p>
<p>Update the .env file, saving the key as <code>DICTIONARY_KEY</code>.</p>
<pre><code class="lang-text">MONGO_SECRET="&lt;password&gt;"
TWILIO_ACCOUNT_SID="&lt;account_sid&gt;"
TWILIO_AUTH_TOKEN="&lt;auth_token&gt;"
TWILIO_NUMBER="&lt;twilio_number&gt;"
TO_NUMBER="&lt;to_number&gt;"
DICTIONARY_API_KEY="&lt;dictionary_key&gt;"
</code></pre>
<p>Update the <code>main.py</code> as follows:</p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> fastapi <span class="hljs-keyword">import</span> FastAPI, Form
<span class="hljs-keyword">import</span> requests
<span class="hljs-keyword">from</span> utils <span class="hljs-keyword">import</span> send_message
<span class="hljs-keyword">from</span> dotenv <span class="hljs-keyword">import</span> load_dotenv
<span class="hljs-keyword">import</span> os
<span class="hljs-keyword">from</span> typing <span class="hljs-keyword">import</span> List

load_dotenv()

app = FastAPI()
whatsapp_number = os.getenv(<span class="hljs-string">"TO_NUMBER"</span>)
api_key = os.getenv(<span class="hljs-string">"DICTIONARY_API_KEY"</span>)

<span class="hljs-meta">@app.post("/message")</span>
<span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">reply</span>(<span class="hljs-params">Body: str = Form(<span class="hljs-params"></span>)</span>):</span>
    url = <span class="hljs-string">f"&lt;https://www.dictionaryapi.com/api/v3/references/collegiate/json/<span class="hljs-subst">{Body}</span>?key=<span class="hljs-subst">{api_key}</span>&gt;"</span>
    response = requests.get(url)
    <span class="hljs-comment"># Extract the JSON data from the response</span>
    data = response.json()

    definition = data[<span class="hljs-number">0</span>][<span class="hljs-string">"shortdef"</span>][<span class="hljs-number">0</span>]

    send_message(whatsapp_number, definition)
</code></pre>
<p><code>@app.post("/message")</code> is a decorator in the fastAPI framework that defines a POST request route to the URL <code>/message</code>. The reply function defined above is called when a POST request is sent to this URL.</p>
<p>The <code>reply</code> function takes in a Body parameter in the request body, which is the message sent to the chatbot (the word you want to get the definition of). It then sends an HTTP request to the Merriam-Webster API to retrieve the word's meaning.</p>
<p>The <code>url</code> variable stores the link to Merriam-Webster API, which takes the <code>Body</code> and the <code>api_key</code> to get details regarding the provided word.</p>
<p>You can make requests from <code>url</code> using <code>requests</code> from the <code>request</code> library and storing <code>request.get(url)</code> into the <code>response</code> variable.</p>
<p>You then extract the JSON data from the response using <code>response.json()</code> and store it in variable data.</p>
<p><code>data[0]["shortdef"][0]</code> allows you to access the short definition of a word stored in the variable definition.</p>
<p><code>send_message()</code> takes the definition and sends it to <code>whatsapp_number</code>.</p>
<p>Next, you'll need to handle situations where someone sends a sentence instead of a word, or a word containing punctuations or characters. So update <code>main.py</code> as follows:</p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> fastapi <span class="hljs-keyword">import</span> FastAPI, Form
<span class="hljs-keyword">import</span> requests
<span class="hljs-keyword">from</span> utils <span class="hljs-keyword">import</span> send_message
<span class="hljs-keyword">from</span> dotenv <span class="hljs-keyword">import</span> load_dotenv
<span class="hljs-keyword">import</span> os
<span class="hljs-keyword">from</span> typing <span class="hljs-keyword">import</span> List
<span class="hljs-keyword">from</span> models <span class="hljs-keyword">import</span> dictionary_collection

load_dotenv()

app = FastAPI()
whatsapp_number = os.getenv(<span class="hljs-string">"TO_NUMBER"</span>)
api_key = os.getenv(<span class="hljs-string">"DICTIONARY_API_KEY"</span>)

<span class="hljs-meta">@app.post("/message")</span>
<span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">reply</span>(<span class="hljs-params">Body: str = Form(<span class="hljs-params"></span>)</span>):</span>
    url = <span class="hljs-string">f"&lt;https://www.dictionaryapi.com/api/v3/references/collegiate/json/<span class="hljs-subst">{Body}</span>?key=<span class="hljs-subst">{api_key}</span>&gt;"</span>
    flag=<span class="hljs-string">"Please give a valid word"</span>

    <span class="hljs-keyword">if</span> Body.isalpha():
        response = requests.get(url)
        <span class="hljs-comment"># Extract the JSON data from the response</span>
        data = response.json()

        definition = data[<span class="hljs-number">0</span>][<span class="hljs-string">"shortdef"</span>][<span class="hljs-number">0</span>]

        send_message(whatsapp_number, definition)
    <span class="hljs-keyword">else</span>:
        <span class="hljs-keyword">return</span> send_message(whatsapp_number, flag)

    <span class="hljs-keyword">return</span> <span class="hljs-string">""</span>
</code></pre>
<p><code>flag</code> is a variable storing the message to give if you provide a sentence or a word with characters.</p>
<p>The <code>if</code> condition checks if a message is a word through <code>Body.isaplha()</code>, if true it gets the definition from Merriam-Webster API if false it returns the function <code>send_message()</code> telling the user to <em>Please give a valid word.</em></p>
<p>To store the words and their meanings to the MongoDB database, update <code>main.py</code> as follows:</p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> fastapi <span class="hljs-keyword">import</span> FastAPI, Form
<span class="hljs-keyword">import</span> requests
<span class="hljs-keyword">from</span> utils <span class="hljs-keyword">import</span> send_message
<span class="hljs-keyword">from</span> dotenv <span class="hljs-keyword">import</span> load_dotenv
<span class="hljs-keyword">import</span> os
<span class="hljs-keyword">from</span> typing <span class="hljs-keyword">import</span> List
<span class="hljs-keyword">from</span> models <span class="hljs-keyword">import</span> dictionary_collection

load_dotenv()

app = FastAPI()
whatsapp_number = os.getenv(<span class="hljs-string">"TO_NUMBER"</span>)
api_key = os.getenv(<span class="hljs-string">"DICTIONARY_API_KEY"</span>)

<span class="hljs-meta">@app.post("/message")</span>
<span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">reply</span>(<span class="hljs-params">Body: str = Form(<span class="hljs-params"></span>)</span>):</span>
    url = <span class="hljs-string">f"&lt;https://www.dictionaryapi.com/api/v3/references/collegiate/json/<span class="hljs-subst">{Body}</span>?key=<span class="hljs-subst">{api_key}</span>&gt;"</span>
    flag=<span class="hljs-string">"Please give a valid word"</span>

    <span class="hljs-keyword">if</span> Body.isalpha():
        response = requests.get(url)
        <span class="hljs-comment"># Extract the JSON data from the response</span>
        data = response.json()

        definition = data[<span class="hljs-number">0</span>][<span class="hljs-string">"shortdef"</span>][<span class="hljs-number">0</span>]

        send_message(whatsapp_number, definition)

        dictionary_db = {<span class="hljs-string">"word"</span>:Body, <span class="hljs-string">"definition"</span>:definition}
        dictionary_collection.insert_one(dictionary_db)

    <span class="hljs-keyword">else</span>:
        <span class="hljs-keyword">return</span> send_message(whatsapp_number, flag)

    <span class="hljs-keyword">return</span> <span class="hljs-string">""</span>
</code></pre>
<p><code>dictionary_db = {"word": Body, "definition": definition}</code> creates a dictionary with two keys, <em>word</em> and <em>definition</em>, and values <em>Body</em> and <em>definition</em>, respectively.</p>
<p><code>dictionary_collection.insert_one(dictionary_db)</code> inserts the dictionary into the MongoDB collection, named <code>dictionary_collection</code>.</p>
<p>You can go to your dashboard and view the items added to the collection.</p>
<p><img src="https://lh6.googleusercontent.com/57-VBBJTN9D7J-0Nhv7gm15kFnf8QrOqajdYc1-1THtnfMhDes2B8ZOtEr02JyskDjTEcwPO4Lpvbe5Hd0-OabelyEcYeh9-jUhtOmEvSDDSHxitTQeScjH6bZivfgadAXT7z3T1yJpOnDRb0i2AvI9PEdPSFI_zAO7F0xa0fQhKGkxR6Aeru0j6aXs3WA" alt="This contains the items that have been sent and received on your application " width="600" height="400" loading="lazy"></p>
<p><em>This contains the items that have been sent and received on your application</em></p>
<h2 id="heading-test-the-chatbot">Test the ChatBot</h2>
<p>Now you can chat with the chatbot and ask for definitions of words:</p>
<p><img src="https://lh3.googleusercontent.com/mZnfLJrDEJwMI7oLO9_a1ILmJjGq_NbEllAy_zbOETOEXZ60OV7XScul8GOWE2kvYM4nFvFX_n0QWQ-ffSTf2p2wfsIO4i66uKVxG80SFjDgLaY99EqWPykryl3EgABNYQaE8sYEaFo_69hgfMm0rd78UtPk-zT7NNfUjfSxC2znO6_JZ1oS7e4TIguJPw" alt="Image showing a chat with the dictionary chatbot" width="600" height="400" loading="lazy"></p>
<p><em>Image showing a chat with the dictionary chatbot</em></p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>In this tutorial, you learned how to create a WhatsApp dictionary chatbot. You learned how to use FastAPI to power the backend of your application, how to interact with Twilio MessagingX WhatsApp API, and how to use NoSQL database like MongoDB to store your data.</p>
<p>You can extend the chatbot to get synonyms and definitions of words with more than one explanation by accessing more metadata from the Merriam-Webster API.</p>
<p>You can check out the Merriam-Webster <a target="_blank" href="https://www.dictionaryapi.com/products/json">API documentation</a> for the various responses you can get. Ensure you read the <a target="_blank" href="https://www.twilio.com/docs/whatsapp/quickstart/python">Twilio WhatsApp API</a> docs for more advanced functionalities like getting media replies and word pronunciation.</p>
 ]]>
                </content:encoded>
            </item>
        
    </channel>
</rss>
