<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: zohir Benmalek</title>
    <description>The latest articles on DEV Community by zohir Benmalek (@benmalek-zohir).</description>
    <link>https://dev.to/benmalek-zohir</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4080496%2Faaec0ce0-d378-4911-832b-d646169ae9ff.png</url>
      <title>DEV Community: zohir Benmalek</title>
      <link>https://dev.to/benmalek-zohir</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/benmalek-zohir"/>
    <language>en</language>
    <item>
      <title>Building a Car Price Predictor with Scikit-learn and Flask</title>
      <dc:creator>zohir Benmalek</dc:creator>
      <pubDate>Tue, 25 Aug 2026 16:46:43 +0000</pubDate>
      <link>https://dev.to/benmalek-zohir/building-a-car-price-predictor-with-scikit-learn-and-flask-36pg</link>
      <guid>https://dev.to/benmalek-zohir/building-a-car-price-predictor-with-scikit-learn-and-flask-36pg</guid>
      <description>&lt;p&gt;Machine learning tutorials often end after &lt;code&gt;model.fit()&lt;/code&gt;. But training a model is only one part of building a useful ML application.&lt;/p&gt;

&lt;p&gt;A more interesting workflow is to take a dataset, prepare the data, engineer useful features, compare several models, save the best pipeline, and finally turn it into a web application.&lt;/p&gt;

&lt;p&gt;That is what this &lt;strong&gt;car price predictor&lt;/strong&gt; project does using &lt;strong&gt;Python, Pandas, Scikit-learn, Joblib, and Flask&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The complete walkthrough is available on &lt;a href="https://softwarejournal.blog/blog/car-price-predictor-sklearn-flask-explained/" rel="noopener noreferrer"&gt;SoftwareJournal.blog&lt;/a&gt;, while the project source code is available on &lt;a href="https://github.com/azario0/car_price_predictor" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Architecture
&lt;/h2&gt;

&lt;p&gt;The project follows a simple machine learning pipeline:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Dataset
   ↓
Data Cleaning
   ↓
Feature Engineering
   ↓
Preprocessing
   ↓
Model Training
   ↓
Model Evaluation
   ↓
Save Pipeline
   ↓
Flask Application
   ↓
Prediction
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The repository contains a Jupyter notebook for experimentation and a Flask application for serving predictions.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;car_price_predictor/
├── notebook.ipynb
├── README.md
└── car_price_predictor/
    ├── app.py
    ├── requirements.txt
    └── templates/
        └── index.html
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Preparing the Dataset
&lt;/h2&gt;

&lt;p&gt;The project uses a second-hand car dataset with fields such as manufacturer, model, engine size, fuel type, year, mileage, and price.&lt;/p&gt;

&lt;p&gt;Pandas is used to load the CSV file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;pandas&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;pd&lt;/span&gt;

&lt;span class="n"&gt;df&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pd&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;read_csv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;car_sales_data.csv&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Before training anything, the notebook checks the dataset using methods such as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;isnull&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;info&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is an important step in any machine learning project. Problems with missing values or unexpected data types are much easier to fix before the training pipeline is created.&lt;/p&gt;

&lt;h2&gt;
  
  
  Feature Engineering
&lt;/h2&gt;

&lt;p&gt;One of the project's main transformations is converting the manufacturing year into the age of the car.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Age&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2024&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Year of manufacture&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The original year column is then removed from the model inputs:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;X&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;drop&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;columns&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Price&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Year of manufacture&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Price&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This gives the model a more directly meaningful feature: &lt;strong&gt;how old is the vehicle?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;There is also an important caveat here. The reference year is hardcoded to &lt;code&gt;2024&lt;/code&gt;, so this should be changed to a dynamic calculation in a production application.&lt;/p&gt;

&lt;h2&gt;
  
  
  Preprocessing with Scikit-learn
&lt;/h2&gt;

&lt;p&gt;The dataset contains both numerical and categorical features.&lt;/p&gt;

&lt;p&gt;Numerical features include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Engine size&lt;/li&gt;
&lt;li&gt;Mileage&lt;/li&gt;
&lt;li&gt;Age&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Categorical features include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Manufacturer&lt;/li&gt;
&lt;li&gt;Fuel type&lt;/li&gt;
&lt;li&gt;Model&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Scikit-learn's &lt;code&gt;ColumnTransformer&lt;/code&gt; makes it possible to process those columns differently.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;sklearn.compose&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;ColumnTransformer&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;sklearn.preprocessing&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;StandardScaler&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;OneHotEncoder&lt;/span&gt;

&lt;span class="n"&gt;preprocessor&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;ColumnTransformer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;transformers&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;num&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;StandardScaler&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;numerical_features&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;cat&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;OneHotEncoder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;handle_unknown&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ignore&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;categorical_features&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;StandardScaler&lt;/code&gt; standardizes numerical values, while &lt;code&gt;OneHotEncoder&lt;/code&gt; converts categories into numerical columns.&lt;/p&gt;

&lt;p&gt;One particularly useful option is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;handle_unknown&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ignore&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This means the application can encounter an unseen categorical value without immediately failing during prediction.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Pipeline Is So Useful
&lt;/h2&gt;

&lt;p&gt;The preprocessing object is combined with the machine learning model:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;sklearn.pipeline&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Pipeline&lt;/span&gt;

&lt;span class="n"&gt;pipeline&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Pipeline&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;preprocessor&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;preprocessor&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;regressor&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;])&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is one of the best design choices in the project.&lt;/p&gt;

&lt;p&gt;Instead of saving preprocessing logic separately from the trained model, the pipeline becomes one object containing the entire process.&lt;/p&gt;

&lt;p&gt;That means the Flask application can later receive raw data and simply call:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;pipeline&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;predict&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;input_data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There is no need to manually perform scaling and one-hot encoding again.&lt;/p&gt;

&lt;p&gt;This significantly reduces the risk of &lt;strong&gt;training-serving inconsistencies&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Comparing Four Models
&lt;/h2&gt;

&lt;p&gt;The project evaluates four regression algorithms:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;models&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;LinearRegression&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;LinearRegression&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Ridge&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Ridge&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;RandomForest&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;RandomForestRegressor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;n_estimators&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;random_state&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;42&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;n_jobs&lt;/span&gt;&lt;span class="o"&gt;=-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;
    &lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;GradientBoosting&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;GradientBoostingRegressor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;n_estimators&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;random_state&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;42&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The dataset is divided into training and testing sets:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;X_train&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;X_test&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;y_train&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;y_test&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;train_test_split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;X&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;test_size&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;0.2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;random_state&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;42&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each model is trained through the same preprocessing pipeline and evaluated using &lt;strong&gt;Mean Absolute Error (MAE)&lt;/strong&gt; and &lt;strong&gt;R²&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The reported results are:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Model&lt;/th&gt;
&lt;th&gt;MAE&lt;/th&gt;
&lt;th&gt;R²&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Linear Regression&lt;/td&gt;
&lt;td&gt;5786.31&lt;/td&gt;
&lt;td&gt;0.7102&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Ridge&lt;/td&gt;
&lt;td&gt;5786.14&lt;/td&gt;
&lt;td&gt;0.7102&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Random Forest&lt;/td&gt;
&lt;td&gt;286.04&lt;/td&gt;
&lt;td&gt;0.9986&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Gradient Boosting&lt;/td&gt;
&lt;td&gt;1037.39&lt;/td&gt;
&lt;td&gt;0.9899&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Random Forest performs the best on this dataset.&lt;/p&gt;

&lt;p&gt;The result is interesting because the linear models struggle to capture the nonlinear relationships between car age, mileage, manufacturer, model, and price.&lt;/p&gt;

&lt;p&gt;Tree-based ensemble models are much better suited to that kind of relationship.&lt;/p&gt;

&lt;p&gt;However, an R² of &lt;code&gt;0.9986&lt;/code&gt; is exceptionally high. The dataset is a mock/synthetic dataset, so these numbers should not be interpreted as evidence that the same model would achieve similar accuracy on a real-world used-car market.&lt;/p&gt;

&lt;h2&gt;
  
  
  Saving the Models
&lt;/h2&gt;

&lt;p&gt;Once the pipelines have been trained, Joblib is used to serialize them:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;joblib&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dump&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;pipeline&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;saved_models/&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;_pipeline.joblib&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This means the trained pipeline can be loaded later without running the complete training process again.&lt;/p&gt;

&lt;p&gt;The winning Random Forest pipeline can then be reloaded:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;loaded_pipeline&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;joblib&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;load&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;saved_models/RandomForest_pipeline.joblib&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Testing the Saved Pipeline
&lt;/h2&gt;

&lt;p&gt;Before connecting the model to Flask, the project tests the serialized pipeline with new examples.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;new_data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pd&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;DataFrame&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Manufacturer&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;BMW&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Ford&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Toyota&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Model&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;X5&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Focus&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Camry&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Engine size&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mf"&gt;4.4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;1.6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;2.5&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Fuel type&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Gasoline&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Gasoline&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Hybrid&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Mileage&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;35000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;80000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;15000&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Age&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;

&lt;span class="n"&gt;predicted_prices&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;loaded_pipeline&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;predict&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;new_data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is a useful test because it verifies that the saved object can be loaded successfully and used with previously unseen input.&lt;/p&gt;

&lt;h2&gt;
  
  
  Connecting the Model to Flask
&lt;/h2&gt;

&lt;p&gt;The next step is turning the trained model into a web application.&lt;/p&gt;

&lt;p&gt;The Flask application loads the pipeline when the server starts:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;joblib&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;load&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;saved_models/RandomForest_pipeline.joblib&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The main route handles both page loading and form submission:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="nd"&gt;@app.route&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;/&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;methods&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;GET&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;POST&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;home&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="bp"&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When the user submits the form, Flask retrieves values such as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;manufacturer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;manufacturer&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;model_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;model&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;year&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;year&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="n"&gt;mileage&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;mileage&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="n"&gt;engine_size&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;float&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;engine_size&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="n"&gt;fuel_type&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;fuel_type&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The application then calculates the vehicle's age and creates a DataFrame using the same column structure used during training.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;input_data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pd&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;DataFrame&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Manufacturer&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;manufacturer&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Model&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;model_name&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Engine size&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;engine_size&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Fuel type&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;fuel_type&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Mileage&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;mileage&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Age&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;age&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Finally:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;prediction&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;predict&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;input_data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The prediction is sent back to the HTML template and displayed to the user.&lt;/p&gt;

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

&lt;p&gt;The application uses a straightforward HTML interface rendered with Jinja2 and styled with Bootstrap.&lt;/p&gt;

&lt;p&gt;Instead of asking users to type arbitrary manufacturer and model names, the interface uses dropdowns.&lt;/p&gt;

&lt;p&gt;That reduces typing mistakes and helps keep the input consistent with the categories the model was trained on.&lt;/p&gt;

&lt;p&gt;The frontend does not require a JavaScript framework or a separate build process. Flask renders the page directly.&lt;/p&gt;

&lt;h2&gt;
  
  
  Running the Application
&lt;/h2&gt;

&lt;p&gt;After installing the dependencies:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-r&lt;/span&gt; requirements.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;the application can be started with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;python car_price_predictor/app.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The Flask development server will normally be available at:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;http://127.0.0.1:5000
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can then enter the vehicle information and receive a predicted price through the browser.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I Like About This Project
&lt;/h2&gt;

&lt;p&gt;The most useful lesson here isn't the particular Random Forest model.&lt;/p&gt;

&lt;p&gt;It is the structure of the project.&lt;/p&gt;

&lt;p&gt;The same preprocessing pipeline is used during training and inference. Multiple algorithms are compared instead of assuming the first model will be good enough. The trained pipeline is persisted so it can be reused later. Finally, Flask provides a simple interface between the model and an ordinary web user.&lt;/p&gt;

&lt;p&gt;That is a much more realistic machine learning workflow than a notebook that simply prints an accuracy score.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Could Be Improved?
&lt;/h2&gt;

&lt;p&gt;There are several improvements that would make this project stronger for production use.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;2024&lt;/code&gt; reference year should be calculated dynamically rather than hardcoded.&lt;/p&gt;

&lt;p&gt;Cross-validation and hyperparameter tuning could provide more reliable model evaluation than relying on a single train/test split.&lt;/p&gt;

&lt;p&gt;The Flask form could also have stronger validation for invalid or missing values.&lt;/p&gt;

&lt;p&gt;Another improvement would be moving feature engineering into shared Python code so that the notebook and Flask application cannot accidentally implement different versions of the same transformation.&lt;/p&gt;

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

&lt;p&gt;This car price predictor is a good example of how a relatively small Python project can connect several important areas of development:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pandas&lt;/strong&gt; handles the data.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Scikit-learn&lt;/strong&gt; handles preprocessing and machine learning.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pipeline&lt;/strong&gt; keeps transformations and prediction together.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Joblib&lt;/strong&gt; stores the trained model.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Flask&lt;/strong&gt; exposes the model through a web application.&lt;/p&gt;

&lt;p&gt;The result is a complete path from dataset to browser:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Raw Data
→ Machine Learning
→ Saved Pipeline
→ Flask
→ Web Prediction
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For developers learning machine learning deployment, this is often the step that makes everything click: the model isn't the entire application. It is one component inside a larger software system.&lt;/p&gt;

&lt;p&gt;You can find the original technical walkthrough on &lt;a href="https://softwarejournal.blog/blog/car-price-predictor-sklearn-flask-explained/" rel="noopener noreferrer"&gt;SoftwareJournal.blog&lt;/a&gt; and the complete source code on &lt;a href="https://github.com/azario0/car_price_predictor" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Originally published on &lt;a href="https://softwarejournal.blog/blog/car-price-predictor-sklearn-flask-explained/" rel="noopener noreferrer"&gt;SoftwareJournal.blog&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>python</category>
      <category>joblib</category>
      <category>webdev</category>
    </item>
    <item>
      <title>I Started a Blog About Software Because I Like Taking Things Apart</title>
      <dc:creator>zohir Benmalek</dc:creator>
      <pubDate>Sun, 23 Aug 2026 21:44:41 +0000</pubDate>
      <link>https://dev.to/benmalek-zohir/i-started-a-blog-about-software-because-i-like-taking-things-apart-d1p</link>
      <guid>https://dev.to/benmalek-zohir/i-started-a-blog-about-software-because-i-like-taking-things-apart-d1p</guid>
      <description>&lt;p&gt;I've always found it more interesting to understand &lt;strong&gt;why something works&lt;/strong&gt; than to just use it.&lt;/p&gt;

&lt;p&gt;When you use an application, you usually don't think about what's happening underneath. You click a button, something loads, data gets saved, an API returns a response, and you move on.&lt;/p&gt;

&lt;p&gt;But as a developer, I tend to wonder about the stuff behind that button.&lt;/p&gt;

&lt;p&gt;How was it built?&lt;/p&gt;

&lt;p&gt;Why did the developer choose that database?&lt;/p&gt;

&lt;p&gt;Why this framework instead of another one?&lt;/p&gt;

&lt;p&gt;What happens when the application gets bigger?&lt;/p&gt;

&lt;p&gt;What happens when something breaks?&lt;/p&gt;

&lt;p&gt;And, probably most importantly, &lt;strong&gt;what can I learn from it?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;That's basically why I started &lt;strong&gt;Software Journal&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;👉 &lt;a href="https://softwarejournal.blog/" rel="noopener noreferrer"&gt;softwarejournal.blog&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  So, what is Software Journal?
&lt;/h2&gt;

&lt;p&gt;It's a small independent software and technology publication where I write about things I'm interested in building, using, and understanding.&lt;/p&gt;

&lt;p&gt;There's no complicated concept behind it.&lt;/p&gt;

&lt;p&gt;I just wanted a place where I could write about software without everything having to fit into a short tutorial or a "10 best tools" article.&lt;/p&gt;

&lt;p&gt;Some articles are about programming.&lt;/p&gt;

&lt;p&gt;Some are about AI.&lt;/p&gt;

&lt;p&gt;Some are about databases or security.&lt;/p&gt;

&lt;p&gt;Others are simply breakdowns of interesting projects.&lt;/p&gt;

&lt;p&gt;The common theme is software and the things around it.&lt;/p&gt;

&lt;h2&gt;
  
  
  I like learning by building
&lt;/h2&gt;

&lt;p&gt;One thing I've noticed about programming is that reading documentation only gets you so far.&lt;/p&gt;

&lt;p&gt;You can read about SQLite for an hour and understand the basic API.&lt;/p&gt;

&lt;p&gt;Then you build something that actually uses SQLite and suddenly you discover ten new things you didn't think about.&lt;/p&gt;

&lt;p&gt;The same thing happens with AI.&lt;/p&gt;

&lt;p&gt;It's easy to write:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;generate&lt;/span&gt;&lt;span class="p"&gt;(...)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But building a real application around that call is a completely different experience.&lt;/p&gt;

&lt;p&gt;You have to think about errors, user input, data, security, interfaces, costs, deployment, and everything else that isn't visible in the first few lines of code.&lt;/p&gt;

&lt;p&gt;That's the kind of stuff I like exploring.&lt;/p&gt;

&lt;h2&gt;
  
  
  Some of the projects I write about
&lt;/h2&gt;

&lt;p&gt;I've written about projects using technologies such as Python, Flask, SQLite, Tkinter, NumPy, SciPy, and Google Gemini.&lt;/p&gt;

&lt;p&gt;For example, I've looked at projects involving things like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;AI-powered applications&lt;/li&gt;
&lt;li&gt;Desktop applications&lt;/li&gt;
&lt;li&gt;Database tools&lt;/li&gt;
&lt;li&gt;Scheduling and optimization&lt;/li&gt;
&lt;li&gt;Security-related utilities&lt;/li&gt;
&lt;li&gt;Web applications&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;What I find interesting isn't just the final result.&lt;/p&gt;

&lt;p&gt;It's the decisions that went into getting there.&lt;/p&gt;

&lt;p&gt;A small project can actually teach you a lot about software engineering when you take the time to look at how all the pieces fit together.&lt;/p&gt;

&lt;h2&gt;
  
  
  I'm not trying to create another "AI news" website
&lt;/h2&gt;

&lt;p&gt;AI is obviously a huge part of software right now, and I'll probably write about it quite a bit.&lt;/p&gt;

&lt;p&gt;But I don't want Software Journal to become another site that publishes an article every time an AI company releases something.&lt;/p&gt;

&lt;p&gt;I'm much more interested in the practical side.&lt;/p&gt;

&lt;p&gt;What can you actually build with these technologies?&lt;/p&gt;

&lt;p&gt;How do these applications work?&lt;/p&gt;

&lt;p&gt;What are the limitations?&lt;/p&gt;

&lt;p&gt;What happens when the demo becomes a real product?&lt;/p&gt;

&lt;p&gt;Those questions are much more interesting to me.&lt;/p&gt;

&lt;h2&gt;
  
  
  Sometimes the simplest projects are the best
&lt;/h2&gt;

&lt;p&gt;I've also started to appreciate something that I probably overlooked earlier:&lt;/p&gt;

&lt;p&gt;You don't always need a huge project to learn something useful.&lt;/p&gt;

&lt;p&gt;A small SQLite application can teach you about data persistence.&lt;/p&gt;

&lt;p&gt;A simple desktop application can teach you about UI state.&lt;/p&gt;

&lt;p&gt;A tiny API can teach you about authentication and error handling.&lt;/p&gt;

&lt;p&gt;A basic AI experiment can teach you about prompting, embeddings, or model limitations.&lt;/p&gt;

&lt;p&gt;You don't need to build the next billion-user platform to learn something valuable.&lt;/p&gt;

&lt;p&gt;Sometimes a weekend project is enough.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why the name "Software Journal"?
&lt;/h2&gt;

&lt;p&gt;Honestly, because that's what I want it to feel like.&lt;/p&gt;

&lt;p&gt;A journal.&lt;/p&gt;

&lt;p&gt;Not a corporate publication trying to predict the future of technology.&lt;/p&gt;

&lt;p&gt;Not a news site chasing every trend.&lt;/p&gt;

&lt;p&gt;Just a growing collection of things I've learned, interesting software I've found, projects I've worked with, and ideas worth exploring.&lt;/p&gt;

&lt;p&gt;Some articles will probably be better than others.&lt;/p&gt;

&lt;p&gt;Some experiments will fail.&lt;/p&gt;

&lt;p&gt;Some technologies that seem exciting today will probably be forgotten later.&lt;/p&gt;

&lt;p&gt;That's fine.&lt;/p&gt;

&lt;p&gt;The point is to keep learning and document some of that process.&lt;/p&gt;

&lt;h2&gt;
  
  
  There's a lot more I want to explore
&lt;/h2&gt;

&lt;p&gt;There are still a ridiculous number of things in software that I want to understand better.&lt;/p&gt;

&lt;p&gt;Distributed systems.&lt;/p&gt;

&lt;p&gt;Better database design.&lt;/p&gt;

&lt;p&gt;AI agents.&lt;/p&gt;

&lt;p&gt;Search and retrieval.&lt;/p&gt;

&lt;p&gt;Compilers.&lt;/p&gt;

&lt;p&gt;Networking.&lt;/p&gt;

&lt;p&gt;Security.&lt;/p&gt;

&lt;p&gt;Infrastructure.&lt;/p&gt;

&lt;p&gt;Different programming languages.&lt;/p&gt;

&lt;p&gt;Open-source projects.&lt;/p&gt;

&lt;p&gt;And a lot of things I haven't even discovered yet.&lt;/p&gt;

&lt;p&gt;So Software Journal is still very much a work in progress.&lt;/p&gt;

&lt;p&gt;I'm basically building the library while I'm learning.&lt;/p&gt;

&lt;h2&gt;
  
  
  If you're curious too
&lt;/h2&gt;

&lt;p&gt;If you enjoy programming, experimenting with new technologies, reading about how applications work, or simply taking software apart to see what's inside, you might find something interesting there.&lt;/p&gt;

&lt;p&gt;You can start here:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://softwarejournal.blog/" rel="noopener noreferrer"&gt;Software Journal&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Or browse the articles directly:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://softwarejournal.blog/blog/" rel="noopener noreferrer"&gt;https://softwarejournal.blog/blog/&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I don't know exactly what Software Journal will look like a year from now.&lt;/p&gt;

&lt;p&gt;That's actually part of the fun.&lt;/p&gt;

&lt;p&gt;For now, I'm just going to keep building things, breaking things, learning things, and writing about them.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>webdev</category>
      <category>programming</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>4u.lat: A Practical Hub for Discovering AI Tools, Software, and Better Ways to Work</title>
      <dc:creator>zohir Benmalek</dc:creator>
      <pubDate>Tue, 18 Aug 2026 00:53:59 +0000</pubDate>
      <link>https://dev.to/benmalek-zohir/4ulat-a-practical-hub-for-discovering-ai-tools-software-and-better-ways-to-work-1859</link>
      <guid>https://dev.to/benmalek-zohir/4ulat-a-practical-hub-for-discovering-ai-tools-software-and-better-ways-to-work-1859</guid>
      <description>&lt;p&gt;The world of artificial intelligence is moving incredibly fast. New models, applications, automation platforms, coding assistants, creative tools, and productivity solutions appear almost every day. For people trying to keep up, the biggest challenge is no longer finding AI tools—it is finding the &lt;strong&gt;right tools&lt;/strong&gt; and understanding how they can actually be useful.&lt;/p&gt;

&lt;p&gt;That is where &lt;strong&gt;4u.lat&lt;/strong&gt; comes in.&lt;/p&gt;

&lt;p&gt;4u.lat is a website dedicated to discovering and exploring &lt;strong&gt;AI tools, software, and practical technology guides&lt;/strong&gt;, bringing useful information together in one place. Instead of forcing visitors to search through countless websites to understand what a tool does or whether it is worth trying, the platform aims to make that discovery process simpler, faster, and more useful.&lt;/p&gt;

&lt;h2&gt;
  
  
  A Place to Discover What AI Can Actually Do
&lt;/h2&gt;

&lt;p&gt;AI is no longer limited to chatbots. Today, there are tools for writing, programming, image generation, video creation, automation, research, productivity, business, and much more.&lt;/p&gt;

&lt;p&gt;4u.lat organizes this rapidly expanding ecosystem into understandable categories, making it easier for visitors to discover technologies that match their needs.&lt;/p&gt;

&lt;p&gt;Whether someone is looking for an AI coding assistant, an image-generation platform, an automation solution, a writing tool, or a new AI model to experiment with, the goal is the same: &lt;strong&gt;help people discover useful technology without unnecessary complexity.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  More Than a List of AI Tools
&lt;/h2&gt;

&lt;p&gt;One of the most valuable aspects of an AI-focused website is context.&lt;/p&gt;

&lt;p&gt;Simply knowing that a tool exists is not enough. People want to know what it does, who it is for, what makes it interesting, and how it can be used in the real world.&lt;/p&gt;

&lt;p&gt;That is why 4u.lat goes beyond simply collecting names and links. Its content can help turn technical developments into information that ordinary users, developers, creators, and technology enthusiasts can understand.&lt;/p&gt;

&lt;p&gt;The result is a more practical approach to AI discovery: instead of asking &lt;em&gt;“What AI tools exist?”&lt;/em&gt;, visitors can start asking &lt;em&gt;“Which tool can solve my problem?”&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Covering Different Areas of Modern AI
&lt;/h2&gt;

&lt;p&gt;The AI ecosystem is incredibly diverse, and 4u.lat reflects that diversity through different areas of technology.&lt;/p&gt;

&lt;p&gt;The site focuses on categories such as &lt;strong&gt;AI tools, AI coding, AI image generation, AI video, AI writing, AI productivity, AI automation, AI agents, AI news, and tutorials&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;This makes the platform useful for different types of visitors.&lt;/p&gt;

&lt;p&gt;A developer may discover a new coding model. A content creator may find an image or video generator. Someone building a business may discover an automation platform. A technology enthusiast may use the site to follow new developments in AI.&lt;/p&gt;

&lt;p&gt;This broad coverage also makes 4u.lat more than a website dedicated to a single AI product or trend. It is designed around the larger ecosystem.&lt;/p&gt;

&lt;h2&gt;
  
  
  Helping People Keep Up With a Fast-Moving Industry
&lt;/h2&gt;

&lt;p&gt;Perhaps the biggest reason a platform like 4u.lat is useful is the speed at which AI changes.&lt;/p&gt;

&lt;p&gt;A tool that seems revolutionary today can be replaced by something better tomorrow. New models constantly improve coding, reasoning, image generation, video, speech, and automation capabilities.&lt;/p&gt;

&lt;p&gt;For users, this creates information overload.&lt;/p&gt;

&lt;p&gt;4u.lat can serve as a starting point for navigating that environment by highlighting interesting tools, technologies, and developments without requiring visitors to follow every AI company, model release, and technical announcement themselves.&lt;/p&gt;

&lt;h2&gt;
  
  
  Practical Guides, Not Just Hype
&lt;/h2&gt;

&lt;p&gt;AI has generated enormous amounts of excitement, but useful technology should ultimately solve real problems.&lt;/p&gt;

&lt;p&gt;Practical guides can help bridge the gap between an impressive AI announcement and actual usage. Instead of simply explaining that a new model exists, good guides can show readers how the technology fits into everyday workflows.&lt;/p&gt;

&lt;p&gt;For example, someone might discover an AI coding tool and then learn how it can be incorporated into a development workflow. Another visitor might find an automation platform and discover ways to eliminate repetitive tasks.&lt;/p&gt;

&lt;p&gt;That practical perspective is important because the value of AI is not only in what the technology can theoretically do—it is in &lt;strong&gt;what people can accomplish with it.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Built for Curious Users
&lt;/h2&gt;

&lt;p&gt;4u.lat is particularly relevant to people who enjoy experimenting with new technology.&lt;/p&gt;

&lt;p&gt;The AI industry rewards curiosity. Trying a new model, discovering a new application, or learning a new workflow can sometimes lead to significant improvements in productivity or creativity.&lt;/p&gt;

&lt;p&gt;A website that brings those discoveries together can become a useful reference point for anyone who wants to stay ahead of the curve.&lt;/p&gt;

&lt;p&gt;From beginners exploring AI for the first time to experienced users searching for their next tool, the platform is positioned around one simple idea: &lt;strong&gt;make modern technology easier to discover and understand.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The Future of 4u.lat
&lt;/h2&gt;

&lt;p&gt;As artificial intelligence continues to develop, websites dedicated to discovering and explaining these technologies will become increasingly valuable.&lt;/p&gt;

&lt;p&gt;The AI ecosystem is growing too quickly for most people to follow everything. Platforms such as 4u.lat can help reduce that complexity by filtering, organizing, and presenting useful information in a way that people can actually use.&lt;/p&gt;

&lt;p&gt;The long-term potential is bigger than simply building a directory of AI products. It is about creating a destination where people can discover new technologies, learn how they work, and find better ways to use them.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why 4u.lat Is Worth Watching
&lt;/h2&gt;

&lt;p&gt;4u.lat represents a simple but increasingly important idea: &lt;strong&gt;technology discovery should be easier.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;With AI evolving at an unprecedented pace, there is enormous value in having a dedicated place to explore new tools, follow important developments, and learn practical ways to use modern software.&lt;/p&gt;

&lt;p&gt;Whether you are a developer, creator, entrepreneur, student, technology enthusiast, or simply someone curious about what AI can do, 4u.lat offers a gateway into a rapidly changing technological landscape.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4u.lat is not just about what AI can do today. It is about helping people discover what they can do with it next.&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>news</category>
      <category>softwareengineering</category>
      <category>programming</category>
    </item>
    <item>
      <title>I’m building TWS, a small platform for audio-visual storytelling</title>
      <dc:creator>zohir Benmalek</dc:creator>
      <pubDate>Sun, 16 Aug 2026 18:52:19 +0000</pubDate>
      <link>https://dev.to/benmalek-zohir/im-building-tws-a-small-platform-for-audio-visual-storytelling-c8i</link>
      <guid>https://dev.to/benmalek-zohir/im-building-tws-a-small-platform-for-audio-visual-storytelling-c8i</guid>
      <description>&lt;p&gt;Hey everyone,&lt;/p&gt;

&lt;p&gt;I’m building &lt;strong&gt;The Whispering Stories (TWS)&lt;/strong&gt; — a small independent project at &lt;strong&gt;&lt;a href="https://tws.rest/" rel="noopener noreferrer"&gt;https://tws.rest/&lt;/a&gt;&lt;/strong&gt;.&lt;/p&gt;

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

&lt;p&gt;The idea came from wanting to experiment with a different way of consuming short stories.&lt;/p&gt;

&lt;p&gt;Instead of presenting a story as a normal page of text, TWS combines &lt;strong&gt;writing, narration, and visual scenes&lt;/strong&gt; into one experience.&lt;/p&gt;

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

&lt;p&gt;You can read the story yourself, or listen to the narration while the scenes change as the story progresses.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why I started it
&lt;/h3&gt;

&lt;p&gt;I’ve always found the boundary between books, podcasts, and video interesting.&lt;/p&gt;

&lt;p&gt;A book gives you complete control over the pace, but everything is left to your imagination.&lt;/p&gt;

&lt;p&gt;A podcast gives you narration and atmosphere, but the visual side is mostly absent.&lt;/p&gt;

&lt;p&gt;Video gives you text, audio, and visuals together, but the creator controls almost the entire pace.&lt;/p&gt;

&lt;p&gt;I wanted to experiment somewhere in the middle.&lt;/p&gt;

&lt;p&gt;With TWS, each story is broken into scenes, with the text, audio, and imagery connected to those scenes.&lt;/p&gt;

&lt;h3&gt;
  
  
  The technical challenge
&lt;/h3&gt;

&lt;p&gt;The interesting part of the project hasn't really been making another website.&lt;/p&gt;

&lt;p&gt;The harder problem is coordinating all of the content.&lt;/p&gt;

&lt;p&gt;A single story can have:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The written narrative&lt;/li&gt;
&lt;li&gt;Individual scenes&lt;/li&gt;
&lt;li&gt;Images for each scene&lt;/li&gt;
&lt;li&gt;Narration&lt;/li&gt;
&lt;li&gt;Timing information&lt;/li&gt;
&lt;li&gt;Metadata for the website&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Those assets need to stay synchronized and load efficiently in the browser.&lt;/p&gt;

&lt;p&gt;I’ve been building the project around a fairly simple web stack and gradually adding the infrastructure needed to handle the content.&lt;/p&gt;

&lt;h3&gt;
  
  
  Keeping the experience simple
&lt;/h3&gt;

&lt;p&gt;I don't want TWS to become another social network or infinite-scroll content site.&lt;/p&gt;

&lt;p&gt;The goal is much simpler:&lt;/p&gt;

&lt;p&gt;Open a story → start reading or listening → experience the story.&lt;/p&gt;

&lt;p&gt;There are no complicated workflows required to understand what the website is for.&lt;/p&gt;

&lt;p&gt;That simplicity is something I’m trying to preserve as the project grows.&lt;/p&gt;

&lt;h3&gt;
  
  
  The part I'm still figuring out
&lt;/h3&gt;

&lt;p&gt;The biggest question for me is whether combining these formats actually makes stories better.&lt;/p&gt;

&lt;p&gt;There are obvious advantages.&lt;/p&gt;

&lt;p&gt;A visual scene can establish a location immediately. Narration can make the experience more immersive. Text gives the reader control.&lt;/p&gt;

&lt;p&gt;But there are also potential problems.&lt;/p&gt;

&lt;p&gt;Too many visual changes could become distracting. Narration might feel too slow or too fast. Images might interfere with the reader's imagination rather than enhance it.&lt;/p&gt;

&lt;p&gt;So I'm treating TWS as an ongoing experiment rather than pretending I've already found the perfect format.&lt;/p&gt;

&lt;h3&gt;
  
  
  What's next
&lt;/h3&gt;

&lt;p&gt;I'm planning to keep expanding the story library while improving the actual reading/listening experience.&lt;/p&gt;

&lt;p&gt;Some of the areas I'm particularly interested in are better synchronization between narration and scenes, improving performance, making the interface more accessible, and eventually making the storytelling format more interactive.&lt;/p&gt;

&lt;p&gt;At this stage, I'm mainly looking for feedback from other indie hackers.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Does this combination of text + narration + visual scenes feel useful to you, or does it feel like unnecessary complexity compared with simply reading a story?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The project is live here:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://tws.rest/" rel="noopener noreferrer"&gt;https://tws.rest/&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I'd love to hear what you think, especially from people who have built content platforms, media projects, or small consumer products themselves.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>content</category>
      <category>storytelling</category>
      <category>webdev</category>
    </item>
  </channel>
</rss>
