<?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: Fahad Ali Khan</title>
    <description>The latest articles on DEV Community by Fahad Ali Khan (@fahadalikhanca).</description>
    <link>https://dev.to/fahadalikhanca</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.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F2024090%2Fb2cd099d-0f69-4d04-b5e1-2d831adc26ee.jpeg</url>
      <title>DEV Community: Fahad Ali Khan</title>
      <link>https://dev.to/fahadalikhanca</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/fahadalikhanca"/>
    <language>en</language>
    <item>
      <title>Building an AI-Generated Text Detector: A Full-Stack NLP Project Guide</title>
      <dc:creator>Fahad Ali Khan</dc:creator>
      <pubDate>Sat, 14 Mar 2026 09:42:40 +0000</pubDate>
      <link>https://dev.to/fahadalikhanca/building-an-ai-generated-text-detector-a-full-stack-nlp-project-guide-45e3</link>
      <guid>https://dev.to/fahadalikhanca/building-an-ai-generated-text-detector-a-full-stack-nlp-project-guide-45e3</guid>
      <description>&lt;p&gt;The line between human and machine writing is blurring fast. This guide walks through building a complete AI-text detection system from scratch — from classical ML baselines to transformer fine-tuning, wrapped in a production API and interactive demo.&lt;/p&gt;

&lt;p&gt;This isn't a toy notebook. By the end, you'll have a modular codebase with an ensemble model, REST API, Gradio UI, Docker deployment, CI/CD, and a test suite. Let's break down each commit.&lt;/p&gt;




&lt;h2&gt;
  
  
  Commit 1: The Foundation — Clean Init
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;2a66fcb Clean init (no large data/models/outputs)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Every good project starts with structure. The initial commit sets up a config-driven architecture where nothing is hardcoded:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;configs/config.yaml&lt;/code&gt;&lt;/strong&gt; centralizes every hyperparameter — TF-IDF feature counts, learning rates, batch sizes, file paths. This means you never dig through scripts to change a setting.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;src/&lt;/code&gt;&lt;/strong&gt; holds reusable library modules. &lt;strong&gt;&lt;code&gt;scripts/&lt;/code&gt;&lt;/strong&gt; holds runnable entry points. This separation matters: your training logic lives in importable functions, not buried inside &lt;code&gt;if __name__ == "__main__"&lt;/code&gt; blocks.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;src/data.py&lt;/code&gt;&lt;/strong&gt; handles schema normalization. Datasets from Kaggle have inconsistent column names — &lt;code&gt;"text"&lt;/code&gt; vs &lt;code&gt;"content"&lt;/code&gt; vs &lt;code&gt;"essay"&lt;/code&gt;, &lt;code&gt;"label"&lt;/code&gt; vs &lt;code&gt;"generated"&lt;/code&gt; vs &lt;code&gt;"is_gpt"&lt;/code&gt;. The &lt;code&gt;normalize_schema()&lt;/code&gt; function maps all variants to a canonical &lt;code&gt;(text, label)&lt;/code&gt; format with binary labels (0=human, 1=AI). This is the kind of defensive data engineering that saves hours of debugging later.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;src/baseline.py&lt;/code&gt;&lt;/strong&gt; implements the classical ML pipeline: TF-IDF vectorization (200K features, unigrams + bigrams) piped into Logistic Regression. The entire pipeline is a single scikit-learn &lt;code&gt;Pipeline&lt;/code&gt; object, which means the vectorizer and classifier are serialized together — no risk of train/serve skew.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;src/transformer.py&lt;/code&gt;&lt;/strong&gt; fine-tunes DistilBERT for binary classification using HuggingFace's &lt;code&gt;Trainer&lt;/code&gt; API. Key design decisions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Automatic validation split creation if one isn't provided&lt;/li&gt;
&lt;li&gt;Null/empty text filtering before tokenization (prevents cryptic errors)&lt;/li&gt;
&lt;li&gt;Mixed-precision training (&lt;code&gt;fp16&lt;/code&gt;) and gradient checkpointing for memory efficiency&lt;/li&gt;
&lt;li&gt;Offline-friendly model loading (checks if &lt;code&gt;model_name&lt;/code&gt; is a local directory)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;.gitignore&lt;/code&gt;&lt;/strong&gt; excludes &lt;code&gt;data/&lt;/code&gt;, &lt;code&gt;models/&lt;/code&gt;, and &lt;code&gt;outputs/&lt;/code&gt; — keeping the repo lightweight. Large binary files don't belong in git.&lt;/p&gt;




&lt;h2&gt;
  
  
  Commit 2: Linguistic Feature Extraction
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;0c716b4 Add linguistic feature extraction module
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Raw text classification is powerful, but interpretability matters. The &lt;code&gt;src/features.py&lt;/code&gt; module extracts &lt;strong&gt;stylometric signals&lt;/strong&gt; — measurable properties of writing style that differ between humans and language models.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What gets extracted:&lt;/strong&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;Why It Matters&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Type-Token Ratio (TTR)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;AI text tends toward lower vocabulary diversity — it reuses common words more&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Hapax Legomena Ratio&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Words used exactly once. Humans use more rare/unique words&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Flesch Reading Ease&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;AI-generated text often clusters in a narrow readability band&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Sentence Length Variation&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Humans write with more variable sentence structure&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Word Entropy&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Shannon entropy of the word distribution — higher means more varied word choice&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Punctuation Rates&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;AI text has distinctive punctuation patterns (fewer semicolons, more consistent comma usage)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The implementation uses zero external NLP libraries — just regex and math. The syllable counter uses a vowel-group heuristic (&lt;code&gt;_syllable_count()&lt;/code&gt;), which is fast and accurate enough for readability formulas.&lt;/p&gt;

&lt;p&gt;The key design choice: &lt;code&gt;extract_features()&lt;/code&gt; returns a flat dictionary, and &lt;code&gt;extract_features_df()&lt;/code&gt; wraps it for batch processing. This makes the features usable both in the API (single predictions) and in training pipelines (DataFrame operations).&lt;/p&gt;




&lt;h2&gt;
  
  
  Commit 3: Ensemble Model
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;b8b8911 Add weighted soft-voting ensemble model
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Neither model alone is optimal. The baseline is fast but misses nuance. The transformer is accurate but slow. The &lt;strong&gt;ensemble&lt;/strong&gt; combines them through weighted probability averaging.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How it works:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;P_ensemble = 0.3 × P_baseline + 0.7 × P_transformer
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Both models output class probabilities (not just labels). The &lt;code&gt;EnsembleDetector&lt;/code&gt; class:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Runs TF-IDF + LogReg to get &lt;code&gt;P(human)&lt;/code&gt; and &lt;code&gt;P(AI)&lt;/code&gt; from the baseline&lt;/li&gt;
&lt;li&gt;Runs DistilBERT inference in batches to get transformer probabilities&lt;/li&gt;
&lt;li&gt;Computes the weighted average&lt;/li&gt;
&lt;li&gt;Returns the argmax as the final prediction&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Why soft voting over hard voting?&lt;/strong&gt; Hard voting (majority rule) throws away confidence information. If the baseline says 51% human and the transformer says 95% AI, hard voting sees a tie. Soft voting correctly favors AI because the transformer's high-confidence signal dominates.&lt;/p&gt;

&lt;p&gt;The weights (0.3/0.7) are configurable via CLI args or environment variables. You could tune them on a validation set, but 0.3/0.7 is a reasonable default given the transformer's higher accuracy.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;scripts/run_ensemble.py&lt;/code&gt; evaluates the ensemble on both validation and test splits, saving JSON metrics for comparison.&lt;/p&gt;




&lt;h2&gt;
  
  
  Commit 4: FastAPI REST API
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;c130c05 Add FastAPI REST API for inference
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A model without an API is a notebook. The &lt;code&gt;api/app.py&lt;/code&gt; module wraps the ensemble detector in a production-grade FastAPI service.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Three endpoints:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;code&gt;GET /health&lt;/code&gt;&lt;/strong&gt; — Returns model load status. Essential for container orchestration (Docker health checks, Kubernetes liveness probes).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;code&gt;POST /predict&lt;/code&gt;&lt;/strong&gt; — Single-text classification. Returns the label, confidence, per-class probabilities, all linguistic features, and inference latency in milliseconds. The latency field is useful for monitoring performance degradation.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;code&gt;POST /predict/batch&lt;/code&gt;&lt;/strong&gt; — Classify up to 64 texts in one request. Batch inference is significantly faster than 64 individual calls because the transformer processes them in GPU-friendly batches.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Design decisions:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Pydantic models&lt;/strong&gt; for request/response validation. &lt;code&gt;PredictRequest&lt;/code&gt; enforces &lt;code&gt;min_length=1&lt;/code&gt; so empty strings are rejected at the schema level, not in model code.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Lifespan context manager&lt;/strong&gt; for model loading. The detector loads once at startup and stays in memory — no per-request loading overhead.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Environment variable configuration&lt;/strong&gt; (&lt;code&gt;BASELINE_WEIGHT&lt;/code&gt;, &lt;code&gt;TRANSFORMER_WEIGHT&lt;/code&gt;, &lt;code&gt;CONFIG_PATH&lt;/code&gt;) so the API is configurable without code changes in deployment.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Run it with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;uvicorn api.app:app &lt;span class="nt"&gt;--host&lt;/span&gt; 0.0.0.0 &lt;span class="nt"&gt;--port&lt;/span&gt; 8000
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;FastAPI auto-generates interactive Swagger docs at &lt;code&gt;/docs&lt;/code&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  Commit 5: Gradio Interactive Demo
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ebf7183 Add Gradio interactive demo with feature analysis
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;APIs are for machines. Demos are for humans. The &lt;code&gt;app.py&lt;/code&gt; file creates a web interface where anyone can paste text and see results instantly.&lt;/p&gt;

&lt;p&gt;The UI has three output components:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Classification label&lt;/strong&gt; with color-coded probabilities (Gradio's &lt;code&gt;Label&lt;/code&gt; component handles this natively)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Verdict text&lt;/strong&gt; — a plain-English summary like "Prediction: AI-generated (confidence: 94.2%)"&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Feature analysis table&lt;/strong&gt; — the linguistic breakdown rendered as a markdown table&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Why Gradio over Streamlit?&lt;/strong&gt; Gradio is purpose-built for ML demos. A &lt;code&gt;gr.Interface&lt;/code&gt; or &lt;code&gt;gr.Blocks&lt;/code&gt; app can be shared with a public URL via &lt;code&gt;share=True&lt;/code&gt;, embedded in HuggingFace Spaces, and requires zero frontend code.&lt;/p&gt;

&lt;p&gt;The demo includes pre-loaded examples so users can test immediately without typing.&lt;/p&gt;




&lt;h2&gt;
  
  
  Commit 6: Unit Tests
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;347fdbc Add unit test suite for features, data, utils, and API
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Tests are non-negotiable for a serious project. The &lt;code&gt;tests/&lt;/code&gt; directory covers four modules:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;test_features.py&lt;/code&gt;&lt;/strong&gt; (22 tests) — The most comprehensive. Tests every feature function individually (vocabulary richness, sentence stats, readability, punctuation, entropy) plus integration tests for the full &lt;code&gt;extract_features()&lt;/code&gt; pipeline. Key edge cases: empty strings, single-word inputs, all-identical words.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;test_data.py&lt;/code&gt;&lt;/strong&gt; — Tests schema normalization with different column name variants (&lt;code&gt;text&lt;/code&gt;/&lt;code&gt;content&lt;/code&gt;/&lt;code&gt;essay&lt;/code&gt;, &lt;code&gt;label&lt;/code&gt;/&lt;code&gt;generated&lt;/code&gt;/&lt;code&gt;is_gpt&lt;/code&gt;), string label mapping, NaN handling, and the split creation function (verifies CSVs are created and row counts sum correctly).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;test_utils.py&lt;/code&gt;&lt;/strong&gt; — Tests seed reproducibility (set seed, generate random numbers, reset seed, verify identical output), directory creation, metric computation (perfect/zero/partial accuracy), and JSON serialization.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;test_api.py&lt;/code&gt;&lt;/strong&gt; — Tests Pydantic schemas without loading actual models. Validates that empty text is rejected, batch requests parse correctly, and response models serialize properly.&lt;/p&gt;

&lt;p&gt;The test structure uses pytest classes to group related tests, making the output easy to scan.&lt;/p&gt;




&lt;h2&gt;
  
  
  Commit 7: Docker Support
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;2c75827 Add Dockerfile and docker-compose for containerized deployment
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;&lt;code&gt;Dockerfile&lt;/code&gt;&lt;/strong&gt; builds a slim Python 3.10 image with CPU-only PyTorch (the full CUDA torch is 2GB+; CPU-only is ~200MB). Models are &lt;strong&gt;not&lt;/strong&gt; baked into the image — they're mounted as volumes at runtime. This keeps the image small and lets you swap models without rebuilding.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;docker-compose.yml&lt;/code&gt;&lt;/strong&gt; orchestrates two services:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;api&lt;/code&gt;&lt;/strong&gt; on port 8000 — the FastAPI service with a health check&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;demo&lt;/code&gt;&lt;/strong&gt; on port 7860 — the Gradio UI, depending on the API service&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Both mount &lt;code&gt;models/&lt;/code&gt; and &lt;code&gt;configs/&lt;/code&gt; as read-only volumes. Environment variables control ensemble weights.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;.dockerignore&lt;/code&gt;&lt;/strong&gt; excludes data, outputs, git history, and the presentation/recording files — keeping the Docker build context small.&lt;/p&gt;

&lt;p&gt;Deploy with one command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker-compose up &lt;span class="nt"&gt;--build&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Commit 8: GitHub Actions CI
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;e8abcfa Add GitHub Actions CI pipeline
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The CI pipeline (&lt;code&gt;.github/workflows/ci.yml&lt;/code&gt;) runs on every push and PR to &lt;code&gt;main&lt;/code&gt;:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Matrix testing&lt;/strong&gt; — Python 3.10 and 3.11 on Ubuntu&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Linting&lt;/strong&gt; — Ruff checks for syntax errors and style issues (&lt;code&gt;E&lt;/code&gt;, &lt;code&gt;F&lt;/code&gt;, &lt;code&gt;W&lt;/code&gt; rules, ignoring line length)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Testing&lt;/strong&gt; — Full pytest suite&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Docker build&lt;/strong&gt; — Validates the Dockerfile builds successfully (runs after tests pass)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;CPU-only PyTorch is installed from the PyTorch index URL to keep CI fast.&lt;/p&gt;




&lt;h2&gt;
  
  
  Commit 9: README and License
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;34953ee Overhaul README and add MIT license
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The README is your project's landing page. The final version includes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;CI badge&lt;/strong&gt; — Green checkmark shows the project builds and tests pass&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Architecture diagram&lt;/strong&gt; — ASCII art showing the ensemble data flow&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Project structure&lt;/strong&gt; — Every file explained with one-line descriptions&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Quick start&lt;/strong&gt; — Four numbered steps from clone to running inference&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;API reference&lt;/strong&gt; — curl examples with sample JSON responses&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Docker deployment&lt;/strong&gt; — One-command setup&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Model details table&lt;/strong&gt; — Hyperparameters at a glance&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Feature documentation&lt;/strong&gt; — What each linguistic feature measures&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tech stack table&lt;/strong&gt; — Every technology organized by category&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ethical considerations&lt;/strong&gt; — Bias risks and usage caveats&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The MIT license makes the project freely usable.&lt;/p&gt;




&lt;h2&gt;
  
  
  What Makes This Resume-Worthy
&lt;/h2&gt;

&lt;p&gt;This project demonstrates competence across the ML engineering stack:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Skill&lt;/th&gt;
&lt;th&gt;Evidence&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;NLP/ML&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;TF-IDF, transformer fine-tuning, ensemble methods, feature engineering&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Software engineering&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Modular architecture, config-driven design, type hints&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;API development&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;FastAPI with Pydantic schemas, batch endpoints, health checks&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Testing&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Pytest suite with edge cases and integration tests&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;DevOps&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Docker, docker-compose, GitHub Actions CI&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Documentation&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Comprehensive README with architecture diagrams and API reference&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Data engineering&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Schema normalization, stratified splitting, null handling&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;It's not just a Jupyter notebook with &lt;code&gt;model.fit()&lt;/code&gt;. It's a deployable system with multiple entry points (CLI scripts, REST API, web demo), proper error handling, and automated quality checks.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;The full source code is available on GitHub. Clone it, train the models, and try the demo yourself.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>machinelearning</category>
      <category>nlp</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Building an Animated Portfolio Hero with GSAP, SplitText, and a Canvas Particle Background</title>
      <dc:creator>Fahad Ali Khan</dc:creator>
      <pubDate>Tue, 10 Feb 2026 10:58:24 +0000</pubDate>
      <link>https://dev.to/fahadalikhanca/building-an-animated-portfolio-hero-with-gsap-splittext-and-a-canvas-particle-background-3d4e</link>
      <guid>https://dev.to/fahadalikhanca/building-an-animated-portfolio-hero-with-gsap-splittext-and-a-canvas-particle-background-3d4e</guid>
      <description>&lt;p&gt;Modern portfolio sites aren’t just about listing projects anymore. They’re an opportunity to demonstrate polish, motion design, and engineering decisions — all in one place.&lt;/p&gt;

&lt;p&gt;Recently, I built an animated hero section that combines:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Character-by-character text reveal using GSAP SplitText&lt;/li&gt;
&lt;li&gt;Liquid morph social icons with hover physics&lt;/li&gt;
&lt;li&gt;A canvas particle background reacting to cursor movement&lt;/li&gt;
&lt;li&gt;Responsive layout that works across devices&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This article walks through the architecture, animation patterns, and lessons learned — so you can build something similar without fighting your layout or performance.&lt;/p&gt;

&lt;p&gt;Here is the final Product: &lt;a href="https://fahadalikhan.vercel.app/" rel="noopener noreferrer"&gt;https://fahadalikhan.vercel.app/&lt;/a&gt; &lt;/p&gt;




&lt;h2&gt;
  
  
  The goal
&lt;/h2&gt;

&lt;p&gt;I wanted a hero section that feels alive without being distracting:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Headline text animates in smoothly&lt;/li&gt;
&lt;li&gt;Social icons pop into view and morph on hover&lt;/li&gt;
&lt;li&gt;A particle field subtly reacts to cursor movement&lt;/li&gt;
&lt;li&gt;Everything stays responsive and performant&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The key was orchestrating multiple animation layers without turning the component into chaos.&lt;/p&gt;




&lt;h2&gt;
  
  
  Layer 1 — Character-by-character text animation
&lt;/h2&gt;

&lt;p&gt;GSAP’s SplitText plugin makes it trivial to animate individual characters. Instead of animating the entire headline block, we split it into spans and animate each char with a stagger.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;split&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;SplitText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;TextRef&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;chars&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nx"&gt;timeline&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;split&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;chars&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;opacity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;duration&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.9&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;stagger&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.05&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;ease&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;power3.out&lt;/span&gt;&lt;span class="dl"&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;This produces a cinematic reveal:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Characters slide in&lt;/li&gt;
&lt;li&gt;Opacity fades up&lt;/li&gt;
&lt;li&gt;Timing feels intentional&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Important cleanup:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;split&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;revert&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Without this, repeated renders stack nested spans and break your DOM.&lt;/p&gt;




&lt;h2&gt;
  
  
  Layer 2 — Social icons with liquid morph hover
&lt;/h2&gt;

&lt;p&gt;Instead of static icons, I wanted something tactile. The trick is animating:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;scale&lt;/li&gt;
&lt;li&gt;rotation&lt;/li&gt;
&lt;li&gt;border-radius&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Border-radius is what creates the organic “blob” shape.&lt;/p&gt;

&lt;p&gt;Hover enter:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;gsap&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;to&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;icon&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;scale&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;1.2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;rotation&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;180&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;borderRadius&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;30% 70% 70% 30% / 30% 30% 70% 70%&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;ease&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;elastic.out(1, 0.3)&lt;/span&gt;&lt;span class="dl"&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;Hover exit:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;gsap&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;to&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;icon&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;scale&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="na"&gt;rotation&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;borderRadius&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;50%&lt;/span&gt;&lt;span class="dl"&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;The elastic easing gives the impression of physical bounce instead of mechanical motion.&lt;/p&gt;




&lt;h2&gt;
  
  
  Layer 3 — Entrance timeline orchestration
&lt;/h2&gt;

&lt;p&gt;One common mistake is running separate animations independently. Instead, everything is sequenced on a GSAP timeline:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;tl&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;gsap&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;timeline&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="nx"&gt;tl&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;textChars&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;span class="k"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;iconLinks&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{...},&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;-=0.3&lt;/span&gt;&lt;span class="dl"&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:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;predictable timing&lt;/li&gt;
&lt;li&gt;overlap control&lt;/li&gt;
&lt;li&gt;easier debugging&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You get a cohesive entrance instead of disconnected animations firing randomly.&lt;/p&gt;




&lt;h2&gt;
  
  
  Layer 4 — Canvas particle background
&lt;/h2&gt;

&lt;p&gt;The particle system runs in a &lt;code&gt;&amp;lt;canvas&amp;gt;&lt;/code&gt; behind the hero content:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;particles arranged in a grid&lt;/li&gt;
&lt;li&gt;mouse proximity drives wave distortion&lt;/li&gt;
&lt;li&gt;rotation aligns particles toward the cursor&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The canvas is positioned absolutely with a negative z-index:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nt"&gt;canvas&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;position&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;absolute&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;inset&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;z-index&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;-1&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;Key performance notes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use requestAnimationFrame&lt;/li&gt;
&lt;li&gt;Reuse particle objects&lt;/li&gt;
&lt;li&gt;Avoid layout reads inside the loop&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This keeps animation smooth even on mid-range devices.&lt;/p&gt;




&lt;h2&gt;
  
  
  Responsiveness challenges
&lt;/h2&gt;

&lt;p&gt;Animation-heavy layouts often break at medium breakpoints. A few practical fixes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Constrain large media with &lt;code&gt;max-width&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Maintain aspect ratios with Tailwind utilities&lt;/li&gt;
&lt;li&gt;Avoid fixed heights where possible&lt;/li&gt;
&lt;/ul&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nt"&gt;md&lt;/span&gt;&lt;span class="nd"&gt;:max-w-&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="err"&gt;450&lt;/span&gt;&lt;span class="nt"&gt;px&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
&lt;span class="nt"&gt;aspect-&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="err"&gt;4&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="err"&gt;3&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
&lt;span class="nt"&gt;mx-auto&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This prevents oversized visuals while preserving composition.&lt;/p&gt;




&lt;h2&gt;
  
  
  UX lessons learned
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Motion should guide attention
&lt;/h3&gt;

&lt;p&gt;Animations should reinforce hierarchy, not steal focus.&lt;/p&gt;

&lt;h3&gt;
  
  
  Physics &amp;gt; gimmicks
&lt;/h3&gt;

&lt;p&gt;Elastic easing feels natural. Linear motion feels robotic.&lt;/p&gt;

&lt;h3&gt;
  
  
  Cleanup matters
&lt;/h3&gt;

&lt;p&gt;Event listeners and SplitText wrappers must be reverted to avoid bugs.&lt;/p&gt;

&lt;h3&gt;
  
  
  Performance first
&lt;/h3&gt;

&lt;p&gt;Canvas and GSAP can coexist — but avoid unnecessary recalculations.&lt;/p&gt;




&lt;h2&gt;
  
  
  Final thoughts
&lt;/h2&gt;

&lt;p&gt;This hero section isn’t about flashy animation. It’s about layering:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;typography motion&lt;/li&gt;
&lt;li&gt;interactive affordances&lt;/li&gt;
&lt;li&gt;subtle background energy&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Together they create a polished first impression while staying performant and maintainable.&lt;/p&gt;

&lt;p&gt;If you’re building a portfolio, landing page, or interactive UI, these techniques scale surprisingly well — and GSAP makes complex motion approachable once you understand timelines and sequencing.&lt;/p&gt;

&lt;p&gt;Happy building.&lt;/p&gt;

</description>
      <category>gsap</category>
      <category>webdev</category>
      <category>ai</category>
      <category>nextjs</category>
    </item>
    <item>
      <title>Trying to blog again...</title>
      <dc:creator>Fahad Ali Khan</dc:creator>
      <pubDate>Mon, 24 Nov 2025 08:29:33 +0000</pubDate>
      <link>https://dev.to/fahadalikhanca/trying-to-blog-again-253f</link>
      <guid>https://dev.to/fahadalikhanca/trying-to-blog-again-253f</guid>
      <description>&lt;p&gt;Hi, guys, I've been away for a long time, mainly because I've been studying full-time and working. With 6 courses each semester at Seneca and a part-time j*b, I felt like I didn't have the time to do anything (except waste time on Apex Legends). So now I've finally graduated from Seneca. Proud to say I've successfully completed my Bachelors of Engineering Software Engineering. These past 4 years haven't been the kindest, but I'm hoping for better opportunities now. So seeing I have some extra time, I've decided to focus on my personal projects. Ideally, I would like to build the next-gen AI model from scratch from the start, but I know I'm not that good (YET!). So I will start a little slow, doing things I like but also focusing on my five-year plan. Stay tuned for exciting projects to come!&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>ai</category>
      <category>softwareengineering</category>
      <category>programming</category>
    </item>
    <item>
      <title>Delivering a Production-Ready Timesheet Automation and Emailing Solution</title>
      <dc:creator>Fahad Ali Khan</dc:creator>
      <pubDate>Fri, 13 Dec 2024 10:51:52 +0000</pubDate>
      <link>https://dev.to/fahadalikhanca/delivering-a-production-ready-timesheet-automation-and-emailing-solution-265c</link>
      <guid>https://dev.to/fahadalikhanca/delivering-a-production-ready-timesheet-automation-and-emailing-solution-265c</guid>
      <description>&lt;h4&gt;
  
  
  Introduction
&lt;/h4&gt;

&lt;p&gt;I began this project to strengthen my Python skills, contribute to an open-source automation tool, and learn to communicate my progress openly. After several weeks of incremental improvements—amid five other courses and internship interviews—I’m proud to release the final version of my contributions to the Academic-Learning-Centre-Admin-Scripts project.&lt;/p&gt;

&lt;p&gt;This post summarizes what I’ve achieved, how I tackled technical and time challenges, and what I learned about producing useful, high-quality open-source contributions in a busy environment.&lt;/p&gt;

&lt;h4&gt;
  
  
  What’s New in the Final Release?
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Weekly Automated Emailing&lt;/strong&gt;:&lt;br&gt;&lt;br&gt;
The script now not only fetches appointment data, updates an Excel timesheet, and saves it with a dynamic filename, but it also sends that timesheet out via email on a predefined schedule (e.g., every Monday). This feature closes the loop, ensuring that the admin office doesn’t need to manually retrieve or request these files.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;User Guide for Deployment&lt;/strong&gt;:&lt;br&gt;&lt;br&gt;
I’ve added a comprehensive &lt;code&gt;USER_GUIDE.md&lt;/code&gt; that details how to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Install dependencies&lt;/li&gt;
&lt;li&gt;Configure paths, tutor IDs, and endpoints&lt;/li&gt;
&lt;li&gt;Manage email credentials securely (e.g., environment variables)&lt;/li&gt;
&lt;li&gt;Set up automated scheduling with cron or Windows Task Scheduler
This documentation should make it straightforward for others to adopt and deploy the script in their own environments.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Refactored and Maintainable Code&lt;/strong&gt;:&lt;br&gt;&lt;br&gt;
Before merging, I refactored the code into cleaner, smaller functions and modules. Now there’s a clear separation of concerns:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;timesheet.py&lt;/code&gt; handles the main workflow.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;email_generator.py&lt;/code&gt; creates structured email data.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;email_sender.py&lt;/code&gt; handles the actual sending of emails.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Constants are clearly defined, date calculations are isolated, and error handling is more graceful. This should pave the way for future contributors to build upon my work.&lt;/p&gt;

&lt;h4&gt;
  
  
  Measuring My Goals and Success
&lt;/h4&gt;

&lt;p&gt;Initially, I set out to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Add email generation and sending features.&lt;/li&gt;
&lt;li&gt;Produce documentation and improve code quality.&lt;/li&gt;
&lt;li&gt;Work in the open (GitHub issues, PRs), write blog posts, and manage time responsibly.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I can confidently say I’ve met these goals:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Email Features:&lt;/strong&gt; Implemented and tested. Emails now go out automatically.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Documentation:&lt;/strong&gt; The user guide and updated README clearly explain setup and usage.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Code Quality:&lt;/strong&gt; The refactoring improved readability and modularity.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Open Communication &amp;amp; Time Management:&lt;/strong&gt;
I wrote blog posts reflecting on my progress and final output. Although I was pressed for time, breaking the work into smaller chunks and documenting it kept me aligned with my goals.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Lessons Learned
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Technical Skills:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
I revisited Python’s datetime handling, file manipulations with &lt;code&gt;openpyxl&lt;/code&gt;, and &lt;code&gt;BeautifulSoup&lt;/code&gt; parsing. I also got hands-on with &lt;code&gt;smtplib&lt;/code&gt; for emailing—learning how to secure credentials and attach files.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Open-Source Collaboration:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Even without extensive back-and-forth from maintainers, I treated this project as if I were part of a larger community—writing clear commit messages, PR descriptions, and linking issues properly. This discipline will serve me well in future projects.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Dealing with Constraints:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Balancing five courses and internship prep was tough. However, setting achievable weekly goals, documenting my progress, and reflecting via blog posts helped me remain productive and not get lost in complexity.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h4&gt;
  
  
  Future Potential
&lt;/h4&gt;

&lt;p&gt;There’s room for more improvements:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Integrating better error handling and logging frameworks.&lt;/li&gt;
&lt;li&gt;Adding automated tests.&lt;/li&gt;
&lt;li&gt;Enabling more dynamic scheduling (e.g., sending emails on multiple days or triggered events).&lt;/li&gt;
&lt;li&gt;Encouraging feedback from the open-source community and possibly mentoring new contributors on the project.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Conclusion
&lt;/h4&gt;

&lt;p&gt;As I reach the conclusion of this effort, I can say I’ve delivered a valuable feature set to an existing open-source project. The script is now not only an automated timesheet updater but also a weekly emailing assistant. The documentation ensures that others can deploy it easily, and the refactoring makes maintenance and extension simpler.&lt;/p&gt;

&lt;p&gt;This was more than a coding exercise: it was an exercise in time management, communication, technical writing, and project stewardship. I’m now more confident in my ability to contribute meaningfully to open-source software, even amidst a heavy personal workload.&lt;/p&gt;

&lt;p&gt;The final result stands as a testament to what careful planning, incremental progress, and open communication can achieve. I look forward to seeing the script help others and potentially collaborating on further enhancements.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Finding My Footing in Open-Source Timesheet Automation</title>
      <dc:creator>Fahad Ali Khan</dc:creator>
      <pubDate>Tue, 10 Dec 2024 08:03:25 +0000</pubDate>
      <link>https://dev.to/fahadalikhanca/finding-my-footing-in-open-source-timesheet-automation-51o</link>
      <guid>https://dev.to/fahadalikhanca/finding-my-footing-in-open-source-timesheet-automation-51o</guid>
      <description>&lt;h3&gt;
  
  
  Blog Post 1: Progress Update
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Introduction
&lt;/h4&gt;

&lt;p&gt;A few days ago, I embarked on contributing to the Academic-Learning-Centre-Admin-Scripts—a Python project that automates the creation and maintenance of weekly timesheets. My ultimate goal was to add new features (like sending the updated Excel timesheets via email), improve documentation, and enhance the overall code quality. Along the way, I’ve also been juggling a heavy workload: I’m taking five other courses and actively preparing for internship interviews, which means every hour spent on this project needed to count.&lt;/p&gt;

&lt;p&gt;Despite these constraints, I’ve made meaningful progress. This update reflects on what I’ve accomplished so far, the challenges I’ve tackled, and how I’ve measured my progress against my initial goals.&lt;/p&gt;

&lt;h4&gt;
  
  
  What I’ve Accomplished So Far
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Email Data Generation&lt;/strong&gt;:&lt;br&gt;&lt;br&gt;
I started by implementing &lt;code&gt;emailDataGenerator&lt;/code&gt;, a function that returns a structured array of email details (recipient, subject, current date, formatted week range, and salutations). Creating this helped me understand Python’s datetime handling more deeply and forced me to pay attention to code structure.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Integrating Email Sending Functionality&lt;/strong&gt;:&lt;br&gt;&lt;br&gt;
After generating data, I implemented &lt;code&gt;sendEmail&lt;/code&gt; to actually dispatch emails. This involved using &lt;code&gt;smtplib&lt;/code&gt; and &lt;code&gt;email.message.EmailMessage&lt;/code&gt; to connect to an SMTP server, format the email, and send it out. The initial attempts led to some trial and error—authenticating with SMTP, managing credentials, and ensuring the email rendered correctly were all new challenges for me.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Refactoring the Codebase&lt;/strong&gt;:&lt;br&gt;&lt;br&gt;
As I introduced new features, I realized the importance of clean, modular code. I refactored &lt;code&gt;timesheet.py&lt;/code&gt; to break logic into smaller functions, used constants for configuration, and set up separate modules (&lt;code&gt;email_generator.py&lt;/code&gt;, &lt;code&gt;email_sender.py&lt;/code&gt;). This not only made the code more maintainable but also helped me clarify my own understanding of the workflow.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Creating a User Guide (Planned)&lt;/strong&gt;:&lt;br&gt;&lt;br&gt;
Although I haven’t fully finished this part, I’ve started outlining a &lt;code&gt;USER_GUIDE.md&lt;/code&gt; that will describe how to deploy the project, configure it, and even schedule it to run automatically. The guide will be the next big step, ensuring that anyone can use or adapt this script without struggling through trial and error.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h4&gt;
  
  
  Challenges and Solutions
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Time Management&lt;/strong&gt;:&lt;br&gt;&lt;br&gt;
With five other courses on my plate and ongoing internship interviews, finding time for open-source contributions was tough. I overcame this by:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Setting small, achievable milestones each week.&lt;/li&gt;
&lt;li&gt;Writing down what I accomplished in blog posts and PR comments, creating a record that motivated me to keep going.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Technical Hurdles&lt;/strong&gt;:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;SMTP &amp;amp; Email Attachments&lt;/strong&gt;: Understanding how to attach the Excel file and handle credentials took some research. I read through Python’s official docs and tested locally until the feature worked reliably.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Refactoring&lt;/strong&gt;: Improving code structure required me to understand every part of the script. By separating logic into functions and modules, I can now navigate the code more easily and add new features without chaos.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Open-Source Etiquette&lt;/strong&gt;:&lt;br&gt;&lt;br&gt;
I learned to write meaningful commit messages, describe PRs thoroughly, and make my branches and merges cleaner. While I haven’t had much direct feedback from maintainers yet, I’m preparing my contributions as if a reviewer is watching carefully.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h4&gt;
  
  
  Adjusting Course for the Final Release
&lt;/h4&gt;

&lt;p&gt;Now that the emailing logic is in place and the code is refactored, I’m focusing on:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Finalizing the user guide with deployment instructions and examples.&lt;/li&gt;
&lt;li&gt;Adding a weekly emailing schedule so that the admin office receives timesheets automatically every Monday (or another chosen day).&lt;/li&gt;
&lt;li&gt;Polishing code style and ensuring I meet PEP 8 guidelines.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;My final blog post will detail the completed features, what I learned, how close I came to my initial goals, and how I overcame time constraints.&lt;/p&gt;

&lt;h4&gt;
  
  
  Conclusion
&lt;/h4&gt;

&lt;p&gt;I’m halfway through my planned tasks and feeling more confident than when I started. Working in Python after a year-long hiatus was challenging, but creating these features and writing about them has solidified my understanding. By my next update, I aim to have the project fully ready for others to adopt, with a user guide and a clean, professional codebase. Despite my busy schedule, I’m making steady, visible progress.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>My Release 0.4 Open-Source Journey - From Planning to Delivery</title>
      <dc:creator>Fahad Ali Khan</dc:creator>
      <pubDate>Tue, 10 Dec 2024 07:56:32 +0000</pubDate>
      <link>https://dev.to/fahadalikhanca/my-release-04-open-source-journey-from-planning-to-delivery-46bk</link>
      <guid>https://dev.to/fahadalikhanca/my-release-04-open-source-journey-from-planning-to-delivery-46bk</guid>
      <description>&lt;h4&gt;
  
  
  Introduction
&lt;/h4&gt;

&lt;p&gt;At the start of this journey, I knew I wanted my last  project of opensource to be something meaningful, educational, and technically rich. The plan was to contribute to an open-source project—in my case, the Academic-Learning-Centre-Admin-Scripts—by adding new features, documenting the process thoroughly, and engaging with the community. The goal was not simply to open a PR and be done, but to do the work in the open, interact on GitHub, refine my changes based on feedback, and ultimately have my contributions accepted and merged.&lt;/p&gt;

&lt;p&gt;This was my first real engagement with a Python-based codebase beyond a basic course I took a year ago. Plus, I’m currently juggling five other courses and navigating internship interviews, which made time management a significant challenge. I needed to set realistic goals, approach them systematically, and track my progress over several weeks.&lt;/p&gt;

&lt;h4&gt;
  
  
  Setting the Stage (Week 1 Plans)
&lt;/h4&gt;

&lt;p&gt;In the first phase, I planned out what I wanted to accomplish:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Why Choose This Project?&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
The Academic-Learning-Centre-Admin-Scripts caught my interest because it automates tedious timesheet generation from tutor appointment data. This felt like a genuinely useful automation that could be extended and improved. I chose it because:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It involves Python scripting and automation (areas I need more real-world practice in).&lt;/li&gt;
&lt;li&gt;It’s already somewhat functional, but clearly has room for enhancements (like automated emailing, documentation improvements, and better deployment instructions).&lt;/li&gt;
&lt;li&gt;Contributing here would let me leave behind a helpful tool.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;What Did I Plan to Do?&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
I decided on a set of tasks:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Improve and modularize email functionality: first generate email data, then send emails automatically each week.&lt;/li&gt;
&lt;li&gt;Enhance the existing documentation by adding a detailed user guide for deployment.&lt;/li&gt;
&lt;li&gt;Eventually refine coding style and structure (PEP 8 compliance, better variable names, etc.).&lt;/li&gt;
&lt;li&gt;Write blog posts and actively use GitHub issues, PRs, and discussions to collaborate in the open.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Approach and Goals:&lt;/strong&gt;  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Allocate a few hours each week specifically to coding and community interaction.&lt;/li&gt;
&lt;li&gt;Keep an eye on the calendar to ensure I finish the core contributions on time.&lt;/li&gt;
&lt;li&gt;Communicate openly: ask questions on GitHub issues, explain what I’m doing in PR descriptions, and write weekly blog posts to reflect on progress.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;By the end of this initial planning phase, I felt confident but cautious—I remembered that I had those five other courses and ongoing internship interviews. Time management was crucial. The plan was to incrementally build my solution and share each step publicly, ensuring I wouldn’t overcommit and lose track.&lt;/p&gt;

&lt;h4&gt;
  
  
  Mid-Project Progress (Week 2 Update)
&lt;/h4&gt;

&lt;p&gt;After about a week, it was time to assess what I had done and where I stood:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;What I Managed to Complete:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;I integrated an &lt;code&gt;emailDataGenerator&lt;/code&gt; function and tested it. This function returned structured email data, including the weekly date range and a friendly closing.
&lt;/li&gt;
&lt;li&gt;I implemented a &lt;code&gt;sendEmail&lt;/code&gt; function capable of dispatching the updated timesheet as an attachment to the admin office. This involved diving into SMTP details, handling attachments, and testing the workflow end-to-end.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Sticking Points:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Handling credentials securely and deciding on which day to send the email was trickier than expected. I learned about environment variables for storing email passwords and considered using cron jobs for scheduling.
&lt;/li&gt;
&lt;li&gt;Balancing this work with my other obligations was tough. I found myself working late at night to implement and test features. However, explaining my work in blog posts and PR descriptions helped clarify my thoughts and keep me motivated.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Adjusting the Plan:&lt;/strong&gt;&lt;br&gt;
With less time than anticipated, I decided to focus on making sure the main features (weekly emailing, user guide) were solid rather than rushing to do everything at once. I communicated any trade-offs on the GitHub issue trackers and in my mid-week blog updates. This open communication might have helped if anyone had feedback or suggestions.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;By this midpoint, I had a working solution that fetched data, updated timesheets, and could now email them automatically (on a chosen weekday, like Monday). I also committed to writing a &lt;code&gt;USER_GUIDE.md&lt;/code&gt; explaining how to deploy and run the script in different environments. The knowledge that I was improving an actual tool was gratifying, even though my schedule was tight.&lt;/p&gt;

&lt;h4&gt;
  
  
  Final Results (Consolidated Outcomes)
&lt;/h4&gt;

&lt;p&gt;Now that the work is completed:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Achievements:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Successfully integrated the weekly emailing feature. The script not only generates a timesheet but also attaches and emails it on schedule.&lt;/li&gt;
&lt;li&gt;Wrote a comprehensive user guide (&lt;code&gt;USER_GUIDE.md&lt;/code&gt;) detailing setup, configuration, scheduling, and secure credential handling.&lt;/li&gt;
&lt;li&gt;Refactored the code to be cleaner, more modular, and easier to maintain. This included adopting a clearer coding style and reorganizing logic into functions and separate files (&lt;code&gt;email_generator.py&lt;/code&gt;, &lt;code&gt;email_sender.py&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;Followed through on the open-source etiquette: made branches, opened PRs, wrote detailed commit messages, and documented the process in blog posts and PR descriptions.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Measuring Success:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The PRs were successfully created, well-described, and reviewed.
&lt;/li&gt;
&lt;li&gt;I learned how to handle date ranges, manipulate Excel files using &lt;code&gt;openpyxl&lt;/code&gt;, parse HTML with &lt;code&gt;BeautifulSoup&lt;/code&gt;, and integrate SMTP emailing.
&lt;/li&gt;
&lt;li&gt;My confidence in Python went from “rusty and unsure” to “capable and resourceful.” I can now handle not only the coding but also explain it clearly to others.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Lessons Learned:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Technical Growth:&lt;/strong&gt; Improving code architecture and adding new features taught me how to read documentation and implement library functions effectively.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Open-Source Process:&lt;/strong&gt; Working in the open, writing technical blog posts, and creating PRs helped me understand the importance of communication and transparency.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Time Management &amp;amp; Priorities:&lt;/strong&gt; Despite five other courses and ongoing internship interviews, breaking the project down into smaller tasks and writing weekly blog updates helped maintain steady progress. Setting realistic goals and adjusting them mid-course was critical.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Community Interaction:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Although I had limited direct feedback from maintainers, writing PR descriptions, linking issues, and documenting changes thoroughly meant that if maintainers or other contributors arrived, they could understand my changes quickly.&lt;/li&gt;
&lt;li&gt;If there were community Slack channels, Discord groups, or GitHub Discussions, I would have participated there as well. The instructions highlighted that being active in community channels and discussions is part of the open-source ethos. Even if minimal feedback came back, the openness and clarity of my workflow prepared me for future collaboration.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h4&gt;
  
  
  Conclusion
&lt;/h4&gt;

&lt;p&gt;What started as a plan to improve a Python script and document my journey ended in a successful completion of all core objectives. I created blog posts (rolled into this single long-form summary), contributed meaningful features, wrote comprehensive documentation, and maintained a professional Git workflow. The experience gave me confidence in my technical and communication skills.&lt;/p&gt;

&lt;p&gt;If anyone else stumbles upon this project looking for guidance on automating timesheets or sending weekly reports via email, I hope my contributions and documentation will help them. Despite my heavy workload—juggling five courses and preparing for internship interviews—I’ve shown that with careful planning, incremental progress, and open communication, one can make a substantial and high-quality contribution to an open-source project.&lt;/p&gt;

&lt;p&gt;This final retrospective closes out my 0.4 journey, capturing the entire arc: from initial planning and goal-setting, through mid-project adaptation and problem-solving, to delivering a polished, documented solution ready to be merged and used.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Implementing and Integrating Email Automation in a Python Timesheet Project</title>
      <dc:creator>Fahad Ali Khan</dc:creator>
      <pubDate>Sun, 08 Dec 2024 04:28:05 +0000</pubDate>
      <link>https://dev.to/fahadalikhanca/implementing-and-integrating-email-automation-in-a-python-timesheet-project-4bbb</link>
      <guid>https://dev.to/fahadalikhanca/implementing-and-integrating-email-automation-in-a-python-timesheet-project-4bbb</guid>
      <description>&lt;p&gt;Below is the updated blog post with the links you’ve provided integrated into the discussion. You can adjust formatting as needed.&lt;/p&gt;




&lt;h3&gt;
  
  
  Blog Post: Implementing and Integrating Email Automation in a Python Timesheet Project
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Date:&lt;/strong&gt; December 8, 2024&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Author:&lt;/strong&gt; Your Name&lt;/p&gt;

&lt;h4&gt;
  
  
  Introduction
&lt;/h4&gt;

&lt;p&gt;This past week, I took on my first real contribution to a Python-based codebase. Although I’ve done a Python course about a year ago, my skills were quite rusty. Before jumping into this project, I spent about 10 hours on a quick Python crash course from FreeCodeCamp (&lt;a href="https://www.freecodecamp.org/learn" rel="noopener noreferrer"&gt;link&lt;/a&gt;) just to refresh my memory on the basics—control structures, data types, standard libraries, and best practices. This preparatory work was necessary because I was about to dive into a code repository that automated certain administrative tasks, and I needed to ensure I was up to speed.&lt;/p&gt;

&lt;h4&gt;
  
  
  Context and Challenges
&lt;/h4&gt;

&lt;p&gt;I’ve been juggling multiple commitments: I’m taking 5 other courses and currently going through internship interviews, so time management has been extremely tough. My goals with these PRs (pull requests) were initially modest—just build a strong foundational understanding of the project’s architecture, and then make incremental contributions. In the spirit of continuous improvement and measuring my progress from my initial baseline (“0.2” confidence level), I set out to do the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Understand the existing timesheet automation code.&lt;/li&gt;
&lt;li&gt;Add a module that generates email data (&lt;code&gt;emailDataGenerator&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;Integrate a new module to send automated emails upon completing the timesheet updates (&lt;code&gt;sendEmail&lt;/code&gt;).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This blog post focuses on detailing my contributions for each PR, the process I followed, what I learned, and how I measured my progress in terms of complexity and comfort working with Python code.&lt;/p&gt;

&lt;h4&gt;
  
  
  Issue #2 and #3: Foundations for Email Data Generation and Sending
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/Krish-Bhalala/Academic-Learning-Centre-Admin-Scripts/issues/2" rel="noopener noreferrer"&gt;Issue #2: Implement email generator #2&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/Krish-Bhalala/Academic-Learning-Centre-Admin-Scripts/issues/3" rel="noopener noreferrer"&gt;Issue #3: Send Email&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These two issues defined the scope of what I needed to achieve: first, create and integrate an email data generator, and second, actually send emails after the timesheet updates.&lt;/p&gt;

&lt;h4&gt;
  
  
  PR #4: Introducing Email Data Generation
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;Link to PR:&lt;/strong&gt; &lt;a href="https://github.com/Krish-Bhalala/Academic-Learning-Centre-Admin-Scripts/pull/4" rel="noopener noreferrer"&gt;PR #4&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;My first PR involved creating a function &lt;code&gt;emailDataGenerator&lt;/code&gt; that returns a structured list containing email details such as the recipient email, subject line, current date, and week range. Before starting, I had limited knowledge of Python’s &lt;code&gt;datetime&lt;/code&gt; module and date handling. I spent a couple of hours experimenting with &lt;code&gt;datetime&lt;/code&gt;, trying to figure out how to compute weekly date ranges (e.g., from Monday to Sunday) and formatting dates using &lt;code&gt;strftime&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What I Did:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Created a separate file &lt;code&gt;email_generator.py&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Implemented &lt;code&gt;emailDataGenerator(receiver, subject, sender)&lt;/code&gt; which returns &lt;code&gt;[receiverEmail, subject, current_date, current_week_range, salutations]&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Used &lt;code&gt;datetime.now()&lt;/code&gt;, &lt;code&gt;timedelta&lt;/code&gt;, and &lt;code&gt;strftime&lt;/code&gt; to produce human-readable date formats.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;What I Learned:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;How to modularize Python code: Separating logic into multiple files makes it cleaner and more maintainable.&lt;/li&gt;
&lt;li&gt;Gained confidence in handling date operations in Python.&lt;/li&gt;
&lt;li&gt;This boosted my comfort from a self-assessed “0.2” (very unsure) to about “0.5” (somewhat confident) with Python, as I had successfully written and integrated a non-trivial function.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Measuring Success:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The PR was merged without major requests for changes.&lt;/li&gt;
&lt;li&gt;I was able to run the script and see the generated email data printed out, confirming correctness.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  PR #5: Sending Automated Emails After Timesheet Updates
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;Link to PR:&lt;/strong&gt; &lt;a href="https://github.com/Krish-Bhalala/Academic-Learning-Centre-Admin-Scripts/pull/5" rel="noopener noreferrer"&gt;PR #5&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The second PR involved more complexity: actually sending emails. I introduced &lt;code&gt;sendEmail(emailData, receiverEmail)&lt;/code&gt; using Python’s &lt;code&gt;smtplib&lt;/code&gt; and &lt;code&gt;email.message.EmailMessage&lt;/code&gt;. This required understanding SMTP, configuring an email server (e.g., Gmail SMTP), and handling authentication. Since this was my first time doing anything email-related in Python, I did the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Created a new module &lt;code&gt;email_sender.py&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Implemented &lt;code&gt;sendEmail&lt;/code&gt; that took the structured &lt;code&gt;emailData&lt;/code&gt; from &lt;code&gt;emailDataGenerator&lt;/code&gt; and dispatched an email via SMTP.&lt;/li&gt;
&lt;li&gt;Handled errors by returning &lt;code&gt;"email not sent"&lt;/code&gt; if any exceptions occurred, or &lt;code&gt;True&lt;/code&gt; if the sending was successful.&lt;/li&gt;
&lt;li&gt;Integrated this into &lt;code&gt;timesheet.py&lt;/code&gt; so that after the Excel timesheet is generated and saved, the script calls &lt;code&gt;emailDataGenerator&lt;/code&gt;, then passes that data to &lt;code&gt;sendEmail&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;What I Learned:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;How to work with &lt;code&gt;smtplib&lt;/code&gt; to establish a secure connection using &lt;code&gt;starttls()&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;The importance of securing credentials. I learned that hardcoding passwords isn’t ideal and considered environment variables or other credential stores for a more secure approach.&lt;/li&gt;
&lt;li&gt;Improved confidence in debugging since my first attempts at sending emails failed due to authentication errors, and I learned to read stack traces and documentation carefully.&lt;/li&gt;
&lt;li&gt;This experience bumped my comfort from “0.5” to about “0.7”. I’m not a Python guru yet, but I’m a lot more comfortable troubleshooting issues and reading official Python documentation now.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Measuring Success:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;After merging the PR, I tested the workflow end-to-end: update timesheet, generate data, send email.&lt;/li&gt;
&lt;li&gt;Verified that an actual email landed in the test recipient’s inbox. That felt incredibly rewarding and concrete.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Process and Time Management Reflections
&lt;/h4&gt;

&lt;p&gt;Time management was a big challenge. I’m juggling multiple courses and internship interviews. However, I managed to be more structured this time:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Block scheduling:&lt;/strong&gt; Dedicated a 3-hour block specifically for Python work on weekends.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Small milestones:&lt;/strong&gt; First, just make sure &lt;code&gt;emailDataGenerator&lt;/code&gt; worked independently. Next, ensure &lt;code&gt;sendEmail&lt;/code&gt; worked with dummy data before integrating with the main code.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Continuous Review:&lt;/strong&gt; Writing about my process in blog posts helped me clarify my thoughts. Explaining things often reveals gaps or suggests improvements.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;By writing this progress report, I’ve recognized how explaining the code and process forced me to better understand it. Every difficulty I faced became clearer once I wrote it down.&lt;/p&gt;

&lt;h4&gt;
  
  
  How I Measured My Progress from 0.2
&lt;/h4&gt;

&lt;p&gt;Initially, I considered myself at a 0.2 comfort level with Python because I had little recent hands-on experience. After these PRs:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Comfort with Python syntax &amp;amp; structures:&lt;/strong&gt; Moved from uncertain to fairly confident. &lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Using third-party libraries:&lt;/strong&gt; I learned to integrate &lt;code&gt;smtplib&lt;/code&gt;, &lt;code&gt;email.message&lt;/code&gt;, &lt;code&gt;datetime&lt;/code&gt;, and &lt;code&gt;openpyxl&lt;/code&gt; more seamlessly.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Contributing to a codebase with specific domain logic:&lt;/strong&gt; I now know how to do weekly date calculations and integrate them into a workflow.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Overall, I’ve gone from 0.2 to about 0.7 in terms of confidence. I’m still not an expert, but I’m significantly more comfortable than before, especially with debugging, modular code design, and handling external libraries.&lt;/p&gt;

&lt;h4&gt;
  
  
  Links and References
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://docs.python.org/3/library/datetime.html" rel="noopener noreferrer"&gt;Python datetime module&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.python.org/3/library/smtplib.html" rel="noopener noreferrer"&gt;smtplib documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.python.org/3/library/email.message.html" rel="noopener noreferrer"&gt;email.message documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.freecodecamp.org/learn" rel="noopener noreferrer"&gt;FreeCodeCamp Python Course&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/Krish-Bhalala/Academic-Learning-Centre-Admin-Scripts/issues/2" rel="noopener noreferrer"&gt;Issue #2: Implement email generator #2&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/Krish-Bhalala/Academic-Learning-Centre-Admin-Scripts/issues/3" rel="noopener noreferrer"&gt;Issue #3: Send Email&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/Krish-Bhalala/Academic-Learning-Centre-Admin-Scripts/pull/4" rel="noopener noreferrer"&gt;PR #4&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/Krish-Bhalala/Academic-Learning-Centre-Admin-Scripts/pull/5" rel="noopener noreferrer"&gt;PR #5&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Conclusion
&lt;/h4&gt;

&lt;p&gt;This series of PRs taught me that incremental learning and improvement, combined with reflective writing, can significantly accelerate skill development. I’m pleased with how I integrated &lt;code&gt;emailDataGenerator&lt;/code&gt; and &lt;code&gt;sendEmail&lt;/code&gt; into the timesheet automation pipeline, and I know that as I take on more complex features, I’ll continue to measure and celebrate my progress—one PR at a time.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Streamlining C++ Project Releases with CMake and Vcpkg</title>
      <dc:creator>Fahad Ali Khan</dc:creator>
      <pubDate>Sat, 23 Nov 2024 18:21:47 +0000</pubDate>
      <link>https://dev.to/fahadalikhanca/streamlining-c-project-releases-with-cmake-and-vcpkg-225p</link>
      <guid>https://dev.to/fahadalikhanca/streamlining-c-project-releases-with-cmake-and-vcpkg-225p</guid>
      <description>&lt;p&gt;Releasing software can often feel like navigating a labyrinth of tools, configurations, and best practices. As a C++ developer, ensuring that your project is easily accessible and installable for users across different platforms is paramount. In this blog post, I'll walk you through the process I undertook to release my C++ project, &lt;strong&gt;&lt;a href="https://github.com/Fahad-Ali-Khan-ca/EnglishFormatter" rel="noopener noreferrer"&gt;EnglishFormatter&lt;/a&gt;&lt;/strong&gt;, using &lt;strong&gt;CMake&lt;/strong&gt; and &lt;strong&gt;Vcpkg&lt;/strong&gt;. I'll share the tools I chose, the step-by-step release process, the lessons learned, the adjustments made to my project, insights from user testing, and comprehensive instructions for users to install and utilize the tool.&lt;/p&gt;

&lt;h2&gt;
  
  
  Table of Contents
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Choosing the Right Tools&lt;/li&gt;
&lt;li&gt;
Process for Creating a Release

&lt;ul&gt;
&lt;li&gt;1. Setting Up the Project with CMake&lt;/li&gt;
&lt;li&gt;2. Managing Dependencies with Vcpkg&lt;/li&gt;
&lt;li&gt;3. Configuring Git for Releases&lt;/li&gt;
&lt;li&gt;4. Building and Testing&lt;/li&gt;
&lt;li&gt;5. Publishing the Release on GitHub&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Lessons Learned&lt;/li&gt;

&lt;li&gt;Adjustments Made to the Project&lt;/li&gt;

&lt;li&gt;User Testing with macOS&lt;/li&gt;

&lt;li&gt;

Installing and Using EnglishFormatter

&lt;ul&gt;
&lt;li&gt;Installation Steps&lt;/li&gt;
&lt;li&gt;Usage Instructions&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Conclusion&lt;/li&gt;

&lt;li&gt;Resources and Links&lt;/li&gt;

&lt;/ul&gt;




&lt;h2&gt;
  
  
  Choosing the Right Tools
&lt;/h2&gt;

&lt;p&gt;Selecting the appropriate tools is crucial for a smooth release process. For &lt;strong&gt;EnglishFormatter&lt;/strong&gt;, I opted for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;CMake&lt;/strong&gt;: A versatile build system generator that simplifies the build process across different platforms.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Vcpkg&lt;/strong&gt;: A C++ library manager that handles dependencies efficiently, ensuring reproducible builds.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;GitHub Releases&lt;/strong&gt;: Leveraging GitHub's built-in release management to distribute binaries and source code.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Links:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://cmake.org/" rel="noopener noreferrer"&gt;CMake Official Website&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/microsoft/vcpkg" rel="noopener noreferrer"&gt;Vcpkg on GitHub&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.github.com/en/repositories/releasing-projects-on-github/about-releases" rel="noopener noreferrer"&gt;GitHub Releases Documentation&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Process for Creating a Release
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Setting Up the Project with CMake
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;CMake&lt;/strong&gt; was chosen as the build system due to its cross-platform capabilities and seamless integration with various package managers. Here's how I configured CMake for &lt;strong&gt;EnglishFormatter&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;CMakeLists.txt&lt;/strong&gt;: Defined the project, set the C++ standard to C++20, and specified the toolchain file for Vcpkg.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cmake"&gt;&lt;code&gt;  &lt;span class="nb"&gt;cmake_minimum_required&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;VERSION 3.20&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="c1"&gt;# Enable Vcpkg manifest mode before the project command&lt;/span&gt;
  &lt;span class="nb"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;VCPKG_MANIFEST_MODE ON CACHE BOOL &lt;span class="s2"&gt;"Enable Vcpkg manifest mode"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="nb"&gt;project&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;EnglishFormatter VERSION 1.0.0 LANGUAGES CXX&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="c1"&gt;# Set C++ standard to C++20&lt;/span&gt;
  &lt;span class="nb"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;CMAKE_CXX_STANDARD 20&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="nb"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;CMAKE_CXX_STANDARD_REQUIRED ON&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="c1"&gt;# ------------------------&lt;/span&gt;
  &lt;span class="c1"&gt;# Core Library Configuration&lt;/span&gt;
  &lt;span class="c1"&gt;# ------------------------&lt;/span&gt;

  &lt;span class="c1"&gt;# Collect all source files for the core library, excluding cli.cpp&lt;/span&gt;
  &lt;span class="nb"&gt;file&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;GLOB CORE_SOURCES CONFIGURE_DEPENDS cli_app/src/*.cpp&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="c1"&gt;# Exclude cli.cpp from CORE_SOURCES to prevent multiple main definitions&lt;/span&gt;
  &lt;span class="nb"&gt;list&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;FILTER CORE_SOURCES EXCLUDE REGEX &lt;span class="s2"&gt;".*/cli&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s2"&gt;.cpp$"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="c1"&gt;# Define the core library&lt;/span&gt;
  &lt;span class="nb"&gt;add_library&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;core_lib STATIC &lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;CORE_SOURCES&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="c1"&gt;# Include directories for the core library&lt;/span&gt;
  &lt;span class="nb"&gt;target_include_directories&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;core_lib PUBLIC cli_app/include&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="c1"&gt;# Find and link CURL and fmt libraries&lt;/span&gt;
  &lt;span class="nb"&gt;find_package&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;CURL REQUIRED&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="nb"&gt;find_package&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;fmt REQUIRED&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="nb"&gt;target_link_libraries&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;core_lib PUBLIC CURL::libcurl fmt::fmt&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="c1"&gt;# ------------------------&lt;/span&gt;
  &lt;span class="c1"&gt;# GoogleTest and GoogleMock Configuration&lt;/span&gt;
  &lt;span class="c1"&gt;# ------------------------&lt;/span&gt;
  &lt;span class="nb"&gt;include&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;FetchContent&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="c1"&gt;# Fetch GoogleTest (which includes GoogleMock)&lt;/span&gt;
  &lt;span class="nf"&gt;FetchContent_Declare&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    googletest
    URL https://github.com/google/googletest/archive/refs/tags/release-1.12.1.zip
    DOWNLOAD_EXTRACT_TIMESTAMP ON
  &lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="c1"&gt;# Prevent overriding the parent project's compiler/linker settings&lt;/span&gt;
  &lt;span class="nb"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;MSVC&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nb"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;gtest_force_shared_crt ON CACHE BOOL &lt;span class="s2"&gt;""&lt;/span&gt; FORCE&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="nb"&gt;endif&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

  &lt;span class="c1"&gt;# Enable building GMock and GTest&lt;/span&gt;
  &lt;span class="nb"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;BUILD_GMOCK ON CACHE BOOL &lt;span class="s2"&gt;""&lt;/span&gt; FORCE&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="nb"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;BUILD_GTEST ON CACHE BOOL &lt;span class="s2"&gt;""&lt;/span&gt; FORCE&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="nf"&gt;FetchContent_MakeAvailable&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;googletest&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="c1"&gt;# Enable testing before defining tests&lt;/span&gt;
  &lt;span class="nb"&gt;enable_testing&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

  &lt;span class="c1"&gt;# ------------------------&lt;/span&gt;
  &lt;span class="c1"&gt;# Main Executable Configuration&lt;/span&gt;
  &lt;span class="c1"&gt;# ------------------------&lt;/span&gt;

  &lt;span class="c1"&gt;# Define the main executable and link it against the core library&lt;/span&gt;
  &lt;span class="nb"&gt;add_executable&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;EnglishFormatter cli_app/src/cli.cpp&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="nb"&gt;target_link_libraries&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;EnglishFormatter PRIVATE core_lib&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="c1"&gt;# ------------------------&lt;/span&gt;
  &lt;span class="c1"&gt;# Test Executable Configuration&lt;/span&gt;
  &lt;span class="c1"&gt;# ------------------------&lt;/span&gt;

  &lt;span class="c1"&gt;# Collect all test source files&lt;/span&gt;
  &lt;span class="nb"&gt;file&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;GLOB TEST_SOURCES CONFIGURE_DEPENDS cli_app/tests/*.cpp&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="c1"&gt;# Define the test executable&lt;/span&gt;
  &lt;span class="nb"&gt;add_executable&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;EnglishFormatterTests &lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;TEST_SOURCES&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="c1"&gt;# Include directories for tests&lt;/span&gt;
  &lt;span class="nb"&gt;target_include_directories&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;EnglishFormatterTests PRIVATE cli_app/include&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="c1"&gt;# Link test executable against GMock, GTest, GTest main, and the core library&lt;/span&gt;
  &lt;span class="nb"&gt;target_link_libraries&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;EnglishFormatterTests 
      PRIVATE 
          gmock 
          gtest 
          gtest_main
          core_lib
  &lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="c1"&gt;# Register the tests&lt;/span&gt;
  &lt;span class="nb"&gt;add_test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;NAME EnglishFormatterTests COMMAND EnglishFormatterTests&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. Managing Dependencies with Vcpkg
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Vcpkg&lt;/strong&gt; was instrumental in managing the project's dependencies, ensuring that all required libraries were correctly installed and linked. Here's how I integrated Vcpkg:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Installing Vcpkg&lt;/strong&gt;:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;  git clone https://github.com/microsoft/vcpkg.git
  &lt;span class="nb"&gt;cd &lt;/span&gt;vcpkg
  ./bootstrap-vcpkg.sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Installing Dependencies&lt;/strong&gt;:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;  ./vcpkg &lt;span class="nb"&gt;install &lt;/span&gt;curl &lt;span class="nb"&gt;fmt&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Using Vcpkg with CMake&lt;/strong&gt;:&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When configuring the project with CMake, I specified the toolchain file provided by Vcpkg:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;  cmake .. &lt;span class="nt"&gt;-DCMAKE_TOOLCHAIN_FILE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;path/to/vcpkg/scripts/buildsystems/vcpkg.cmake
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: Replace &lt;code&gt;path/to/vcpkg&lt;/code&gt; with the actual path to your Vcpkg installation.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Configuring Git for Releases
&lt;/h3&gt;

&lt;p&gt;Git tags are pivotal in marking specific points in the project's history, such as releases. Here's how I managed Git tags:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Committing Changes&lt;/strong&gt;:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;  git add &lt;span class="nb"&gt;.&lt;/span&gt;
  git commit &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"Prepare for release 1.0.0"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Creating an Annotated Tag&lt;/strong&gt;:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;  git tag &lt;span class="nt"&gt;-a&lt;/span&gt; v1.0.0 &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"Release version 1.0.0"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Pushing Tags to GitHub&lt;/strong&gt;:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;  git push origin main
  git push &lt;span class="nt"&gt;--follow-tags&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This approach ensures that the release is clearly marked in the project's history and is easily accessible for future reference.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Building and Testing
&lt;/h3&gt;

&lt;p&gt;With the project configured, the next step was to build and test it to ensure everything functioned as expected.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Building the Project&lt;/strong&gt;:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;  &lt;span class="nb"&gt;mkdir &lt;/span&gt;build
  &lt;span class="nb"&gt;cd &lt;/span&gt;build
  cmake .. &lt;span class="nt"&gt;-DCMAKE_TOOLCHAIN_FILE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;../vcpkg/scripts/buildsystems/vcpkg.cmake
  cmake &lt;span class="nt"&gt;--build&lt;/span&gt; &lt;span class="nb"&gt;.&lt;/span&gt; &lt;span class="nt"&gt;--config&lt;/span&gt; Release
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Running Tests&lt;/strong&gt;:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;  ctest &lt;span class="nt"&gt;--output-on-failure&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This process verified that the core library and executables were correctly built and that the tests passed, ensuring the reliability of the release.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Publishing the Release on GitHub
&lt;/h3&gt;

&lt;p&gt;Publishing the release on GitHub made it accessible to users and integrated with the project's version control.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Creating a Release on GitHub&lt;/strong&gt;:&lt;/li&gt;
&lt;/ul&gt;

&lt;ol&gt;
&lt;li&gt;Navigate to the GitHub repository.&lt;/li&gt;
&lt;li&gt;Click on the &lt;strong&gt;"Releases"&lt;/strong&gt; tab.&lt;/li&gt;
&lt;li&gt;Click &lt;strong&gt;"Draft a new release"&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Select the tag &lt;code&gt;v1.0.0&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Provide a release title and description.&lt;/li&gt;
&lt;li&gt;Attach any build artifacts if necessary (e.g., binaries for different platforms).&lt;/li&gt;
&lt;li&gt;Click &lt;strong&gt;"Publish release"&lt;/strong&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This step officially marks the version &lt;code&gt;1.0.0&lt;/code&gt; of &lt;strong&gt;EnglishFormatter&lt;/strong&gt; as available for users to download and install.&lt;/p&gt;




&lt;h2&gt;
  
  
  Lessons Learned
&lt;/h2&gt;

&lt;p&gt;Embarking on this release journey was both enlightening and challenging. Here are some key takeaways:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Importance of Proper Configuration Order&lt;/strong&gt;: Setting variables like &lt;code&gt;CMAKE_TOOLCHAIN_FILE&lt;/code&gt; and &lt;code&gt;VCPKG_MANIFEST_MODE&lt;/code&gt; before the &lt;code&gt;project()&lt;/code&gt; command in &lt;code&gt;CMakeLists.txt&lt;/code&gt; was crucial. Misplacing these led to initial configuration issues.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Managing Dependencies&lt;/strong&gt;: Vcpkg simplified dependency management, but ensuring all dependencies were correctly listed in &lt;code&gt;vcpkg.json&lt;/code&gt; prevented potential build issues.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Git Tagging Best Practices&lt;/strong&gt;: Using annotated tags with clear messages aids in maintaining a clean project history and facilitates easier rollbacks if needed.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Documentation is Key&lt;/strong&gt;: Clear and comprehensive documentation in &lt;code&gt;README.md&lt;/code&gt; ensures users can install and use the tool without hiccups.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;User Testing Insights&lt;/strong&gt;: Real-world testing highlighted areas where documentation could be improved, emphasizing the need for user-centric documentation.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  Adjustments Made to the Project
&lt;/h2&gt;

&lt;p&gt;To accommodate the release process using CMake and Vcpkg, several modifications were necessary:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Integration of Vcpkg&lt;/strong&gt;: Added &lt;code&gt;vcpkg.json&lt;/code&gt; to manage dependencies and adjusted &lt;code&gt;CMakeLists.txt&lt;/code&gt; to enable Vcpkg manifest mode.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Build Configuration&lt;/strong&gt;: Configured output directories in CMake to organize binaries systematically.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Testing Setup&lt;/strong&gt;: Incorporated GoogleTest and GoogleMock for unit testing, ensuring the core functionalities were reliable.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Documentation Enhancements&lt;/strong&gt;: Expanded &lt;code&gt;README.md&lt;/code&gt; with detailed installation, configuration, and usage instructions to guide users effectively.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These changes streamlined the build process, ensured dependency consistency, and enhanced the overall usability of &lt;strong&gt;EnglishFormatter&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  User Testing with macOS
&lt;/h2&gt;

&lt;p&gt;To validate the installation and usage instructions, I enlisted the help of a friend who uses macOS. Here's how the session unfolded:&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Setup&lt;/strong&gt;
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Preparation&lt;/strong&gt;: Shared the updated &lt;code&gt;README.md&lt;/code&gt; with my friend, highlighting the installation steps.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Environment&lt;/strong&gt;: My friend ensured they had CMake, Vcpkg, and a C++20-compatible compiler installed on their macOS system.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Testing Process&lt;/strong&gt;
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Cloning the Repository&lt;/strong&gt;:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   git clone https://github.com/yourusername/EnglishFormatter.git
   &lt;span class="nb"&gt;cd &lt;/span&gt;EnglishFormatter
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Setting Up Vcpkg&lt;/strong&gt;:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   git clone https://github.com/microsoft/vcpkg.git
   &lt;span class="nb"&gt;cd &lt;/span&gt;vcpkg
   ./bootstrap-vcpkg.sh
   ./vcpkg &lt;span class="nb"&gt;install &lt;/span&gt;curl &lt;span class="nb"&gt;fmt
   cd&lt;/span&gt; ..
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Configuring and Building the Project&lt;/strong&gt;:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   &lt;span class="nb"&gt;mkdir &lt;/span&gt;build
   &lt;span class="nb"&gt;cd &lt;/span&gt;build
   cmake .. &lt;span class="nt"&gt;-DCMAKE_TOOLCHAIN_FILE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;../vcpkg/scripts/buildsystems/vcpkg.cmake
   cmake &lt;span class="nt"&gt;--build&lt;/span&gt; &lt;span class="nb"&gt;.&lt;/span&gt; &lt;span class="nt"&gt;--config&lt;/span&gt; Release
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Running the Application&lt;/strong&gt;:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   ./EnglishFormatter
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;strong&gt;Observations and Feedback&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Smooth Installation&lt;/strong&gt;: The installation steps were clear, and my friend was able to set up the environment without issues.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Execution Clarity&lt;/strong&gt;: Running the executable and navigating the interactive menu was straightforward.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Minor Confusion&lt;/strong&gt;: Initially, my friend was unsure about specifying the path to the Vcpkg toolchain file. Clarifying this step helped resolve the confusion.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Documentation Improvements&lt;/strong&gt;: Based on the feedback, I added more explicit instructions regarding the toolchain file path and included troubleshooting tips for common issues.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Corrections Made&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Toolchain File Path&lt;/strong&gt;: Provided a clearer explanation of how to locate and specify the Vcpkg toolchain file during the CMake configuration.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Environment Setup&lt;/strong&gt;: Included additional details on ensuring that Vcpkg is correctly set up before building the project.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This user testing session was invaluable in refining the documentation, ensuring that users across different platforms can effortlessly install and utilize &lt;strong&gt;EnglishFormatter&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  Installing and Using EnglishFormatter
&lt;/h2&gt;

&lt;p&gt;With the release now live, users can easily install and use &lt;strong&gt;EnglishFormatter&lt;/strong&gt; on their systems. Here's a comprehensive guide to get you started.&lt;/p&gt;

&lt;h3&gt;
  
  
  Installation Steps
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Install Vcpkg&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Vcpkg&lt;/strong&gt; is essential for managing dependencies. Follow these steps to install it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   git clone https://github.com/microsoft/vcpkg.git
   &lt;span class="nb"&gt;cd &lt;/span&gt;vcpkg
   ./bootstrap-vcpkg.sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For detailed instructions, refer to the &lt;a href="https://github.com/microsoft/vcpkg#quick-start" rel="noopener noreferrer"&gt;Vcpkg Quick Start Guide&lt;/a&gt;.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Clone the EnglishFormatter Repository&lt;/strong&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   git clone https://github.com/yourusername/EnglishFormatter.git
   &lt;span class="nb"&gt;cd &lt;/span&gt;EnglishFormatter
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Set Up the &lt;code&gt;.env&lt;/code&gt; File&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Create a &lt;code&gt;.env&lt;/code&gt; file in the project's root directory to store your API key:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;   API_KEY=your_api_key_here
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Replace &lt;code&gt;your_api_key_here&lt;/code&gt; with your actual API key from your language model provider (e.g., OpenAI).&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Build the Project&lt;/strong&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   &lt;span class="nb"&gt;mkdir &lt;/span&gt;build
   &lt;span class="nb"&gt;cd &lt;/span&gt;build
   cmake .. &lt;span class="nt"&gt;-DCMAKE_TOOLCHAIN_FILE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;../vcpkg/scripts/buildsystems/vcpkg.cmake
   cmake &lt;span class="nt"&gt;--build&lt;/span&gt; &lt;span class="nb"&gt;.&lt;/span&gt; &lt;span class="nt"&gt;--config&lt;/span&gt; Release
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: Ensure that the path to &lt;code&gt;vcpkg&lt;/code&gt; in the &lt;code&gt;CMAKE_TOOLCHAIN_FILE&lt;/code&gt; flag is correct based on your system setup.&lt;/p&gt;

&lt;h3&gt;
  
  
  Usage Instructions
&lt;/h3&gt;

&lt;p&gt;Once built, you can use &lt;strong&gt;EnglishFormatter&lt;/strong&gt; to format, summarize, or paraphrase your text documents.&lt;/p&gt;

&lt;h4&gt;
  
  
  Running via Command-Line Options
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;./EnglishFormatter &lt;span class="o"&gt;[&lt;/span&gt;options]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Available Options:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;-h, --help&lt;/code&gt; : Show help message and exit.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;-v, --version&lt;/code&gt; : Show the tool's version and exit.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;-m, --model MODEL&lt;/code&gt; : Specify the language model to use (default: gpt-3.5-turbo).&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;-o, --output SUFFIX&lt;/code&gt; : Specify the output file suffix (default: _modified).&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;-t, --token-usage&lt;/code&gt; : Show token usage and exit.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Formatting documents with a specific model and output suffix:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;./EnglishFormatter &lt;span class="nt"&gt;--model&lt;/span&gt; gpt-4 &lt;span class="nt"&gt;--output&lt;/span&gt; _formatted
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Using the Interactive Menu
&lt;/h4&gt;

&lt;p&gt;Simply run the executable without any arguments to access the interactive menu:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;./EnglishFormatter
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Menu Options:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Format document&lt;/strong&gt;: Improve the readability and structure of your text files.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Summarize document&lt;/strong&gt;: Generate concise summaries of your documents.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Paraphrase document&lt;/strong&gt;: Rephrase your text while retaining the original meaning.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Exit&lt;/strong&gt;: Close the application.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Navigation:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use the &lt;strong&gt;Up&lt;/strong&gt; and &lt;strong&gt;Down&lt;/strong&gt; arrow keys to navigate through the menu.&lt;/li&gt;
&lt;li&gt;Press &lt;strong&gt;Enter&lt;/strong&gt; to select an option.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Processing Files:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Select the desired action from the menu.&lt;/li&gt;
&lt;li&gt;When prompted, enter the names of the files you wish to process, separated by spaces.&lt;/li&gt;
&lt;li&gt;The tool will process each file and save the output with the specified suffix.&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Releasing &lt;strong&gt;EnglishFormatter&lt;/strong&gt; was a rewarding experience that underscored the importance of structured build systems, efficient dependency management, and comprehensive documentation. By leveraging &lt;strong&gt;CMake&lt;/strong&gt; and &lt;strong&gt;Vcpkg&lt;/strong&gt;, I ensured that the project is easily buildable across different platforms, making it accessible to a broader user base. The user testing session highlighted the significance of clear instructions, prompting necessary refinements to the documentation. As a result, users can now seamlessly install and utilize &lt;strong&gt;EnglishFormatter&lt;/strong&gt;, enhancing their text processing tasks with advanced language models.&lt;/p&gt;




&lt;h2&gt;
  
  
  Resources and Links
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://cmake.org/documentation/" rel="noopener noreferrer"&gt;CMake Official Documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/microsoft/vcpkg" rel="noopener noreferrer"&gt;Vcpkg Package Manager&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.github.com/en/repositories/releasing-projects-on-github/about-releases" rel="noopener noreferrer"&gt;GitHub Releases&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/google/googletest" rel="noopener noreferrer"&gt;GoogleTest Documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/nlohmann/json" rel="noopener noreferrer"&gt;nlohmann/json GitHub Repository&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/motdotla/dotenv-cpp" rel="noopener noreferrer"&gt;dotenv-cpp GitHub Repository&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://beta.openai.com/docs/" rel="noopener noreferrer"&gt;OpenAI API Documentation&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  - &lt;a href="https://github.com/Fahad-Ali-Khan-ca/EnglishFormatter" rel="noopener noreferrer"&gt;Github Repo&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Feel free to reach out via the &lt;a href="https://github.com/Fahad-Ali-Khan-ca/EnglishFormatter/issues" rel="noopener noreferrer"&gt;GitHub Issues&lt;/a&gt; page or contact me directly for any questions, suggestions, or support regarding &lt;strong&gt;EnglishFormatter&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Happy Formatting!&lt;/p&gt;

</description>
      <category>cpp</category>
      <category>c</category>
      <category>backenddevelopment</category>
      <category>softwareengineering</category>
    </item>
    <item>
      <title>Continuous Integration with GitHub Actions</title>
      <dc:creator>Fahad Ali Khan</dc:creator>
      <pubDate>Thu, 21 Nov 2024 11:05:03 +0000</pubDate>
      <link>https://dev.to/fahadalikhanca/continuous-integration-with-github-actions-4f3j</link>
      <guid>https://dev.to/fahadalikhanca/continuous-integration-with-github-actions-4f3j</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;In Lab 8 of DPS909, I explored the power of &lt;strong&gt;Continuous Integration (CI)&lt;/strong&gt;, specifically through &lt;strong&gt;GitHub Actions&lt;/strong&gt;. This lab was a great opportunity to enhance my project by automating tests, ensuring quality control, and learning to integrate workflows into real-world development practices.&lt;/p&gt;

&lt;p&gt;CI ensures that code remains functional and bug-free with every change. It prevents breaking the default branch by continuously running tests. For this lab, I not only integrated CI into my own project but also contributed tests to my partner’s project. This blog post reflects on my journey through these tasks.&lt;/p&gt;




&lt;h2&gt;
  
  
  Setting Up GitHub Actions for My Project
&lt;/h2&gt;

&lt;p&gt;To set up CI in my project, I created a &lt;strong&gt;GitHub Actions Workflow&lt;/strong&gt;. This workflow was triggered whenever:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A push was made to the &lt;code&gt;main&lt;/code&gt; branch.&lt;/li&gt;
&lt;li&gt;A pull request was created targeting the &lt;code&gt;main&lt;/code&gt; branch.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  YAML Workflow Configuration
&lt;/h3&gt;

&lt;p&gt;Below is the YAML file I used for my GitHub Actions workflow:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;CI Workflow&lt;/span&gt;

&lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;push&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;branches&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;main&lt;/span&gt;
  &lt;span class="na"&gt;pull_request&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;branches&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;main&lt;/span&gt;

&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;build-and-test&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;

    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Checkout repository&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/checkout@v3&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Set up C++&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/setup-cpp@v1&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;compiler&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;gcc&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Build the project&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
          &lt;span class="s"&gt;mkdir build&lt;/span&gt;
          &lt;span class="s"&gt;cd build&lt;/span&gt;
          &lt;span class="s"&gt;cmake ..&lt;/span&gt;
          &lt;span class="s"&gt;make&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Run Tests&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
          &lt;span class="s"&gt;cd build&lt;/span&gt;
          &lt;span class="s"&gt;ctest&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This workflow checks out my repository, builds the project using &lt;strong&gt;CMake&lt;/strong&gt;, and runs the tests I wrote in Lab 7. &lt;/p&gt;




&lt;h2&gt;
  
  
  Testing CI with a Pull Request
&lt;/h2&gt;

&lt;p&gt;To ensure the workflow was working as expected, I:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Created a new branch, &lt;code&gt;add-more-tests&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Added new tests for a different function in my project.&lt;/li&gt;
&lt;li&gt;Pushed the branch to my repository and opened a pull request targeting the &lt;code&gt;main&lt;/code&gt; branch.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The CI workflow ran as expected:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Initially, I broke one of the tests intentionally to observe a failure. The logs clearly showed the issue, which made debugging straightforward.&lt;/li&gt;
&lt;li&gt;After fixing the test, the CI passed, confirming the workflow's success.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Merging this pull request into the &lt;code&gt;main&lt;/code&gt; branch gave me confidence that my project was protected from unintentional bugs.&lt;/p&gt;




&lt;h2&gt;
  
  
  Contributing Tests to a Partner’s Project
&lt;/h2&gt;

&lt;p&gt;In the second part of the lab, I collaborated with my classmate, Inder Parmar, and contributed tests to their repository, &lt;a href="https://github.com/InderParmar/Tailor4Job" rel="noopener noreferrer"&gt;Tailor4Job&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  My Pull Request: &lt;a href="https://github.com/InderParmar/Tailor4Job/pull/11" rel="noopener noreferrer"&gt;#11&lt;/a&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Task&lt;/strong&gt;: I added a test case for their &lt;code&gt;jobFilter&lt;/code&gt; function to ensure it handles edge cases correctly.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Challenges&lt;/strong&gt;: Their repository used a different framework and setup than mine. Understanding their testing tools and project structure took some time.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Outcome&lt;/strong&gt;: My pull request passed their CI workflow successfully. This experience taught me the importance of writing tests that align with a project’s existing structure and guidelines.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Reflection on Continuous Integration
&lt;/h2&gt;

&lt;p&gt;Setting up CI was a game-changer for my development workflow. Here are some key takeaways:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Proactive Bug Prevention&lt;/strong&gt;: CI ensures bugs are caught early, reducing the risk of breaking the default branch.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ease of Collaboration&lt;/strong&gt;: Automated tests give confidence when merging code from multiple developers.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Improved Debugging&lt;/strong&gt;: CI logs provided detailed insights into test failures, making debugging faster and more efficient.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Collaborating on a partner's repo was an enriching experience, as it gave me exposure to a different codebase, testing environment, and workflow.&lt;/p&gt;




&lt;h2&gt;
  
  
  Optional Challenges
&lt;/h2&gt;

&lt;p&gt;While I didn’t fully implement the optional challenges, I explored:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Adding a Linter&lt;/strong&gt;: Automating linting as part of CI helps catch style and syntax issues early.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Development Containers&lt;/strong&gt;: I experimented with setting up a reproducible development environment using Docker and Codespaces.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;These steps can further enhance project quality and ease of onboarding for new contributors.&lt;/p&gt;




&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Lab 8 taught me the importance of integrating CI workflows into development projects. CI ensures consistent quality control and fosters collaboration, making it an invaluable tool in modern software development.&lt;/p&gt;

&lt;p&gt;You can check out my project’s successful CI run and the pull request to my partner’s project below:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;CI Workflow Run&lt;/strong&gt;: &lt;a href="https://github.com/Fahad-Ali-Khan-ca/EnglishFormatter/actions" rel="noopener noreferrer"&gt;GitHub Actions&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Partner's Repo PR&lt;/strong&gt;: &lt;a href="https://github.com/InderParmar/Tailor4Job/pull/11" rel="noopener noreferrer"&gt;Pull Request #11&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This lab has truly enhanced my understanding of automation, testing, and collaboration in open-source development.&lt;/p&gt;

</description>
      <category>beginners</category>
      <category>programming</category>
      <category>c</category>
      <category>cpp</category>
    </item>
    <item>
      <title>Testing Frameworks in Action: A Deep Dive into Automated Testing for EnglishFormatter</title>
      <dc:creator>Fahad Ali Khan</dc:creator>
      <pubDate>Wed, 20 Nov 2024 02:51:54 +0000</pubDate>
      <link>https://dev.to/fahadalikhanca/testing-frameworks-in-action-a-deep-dive-into-automated-testing-for-englishformatter-50mj</link>
      <guid>https://dev.to/fahadalikhanca/testing-frameworks-in-action-a-deep-dive-into-automated-testing-for-englishformatter-50mj</guid>
      <description>&lt;p&gt;Automated testing is an essential part of any robust software development workflow. It ensures code quality, minimizes regressions, and provides confidence in the software’s behavior. In this blog, I’ll share my journey through Lab 7, which revolved around incorporating testing into my &lt;strong&gt;EnglishFormatter&lt;/strong&gt; project. From selecting tools to mocking responses and uncovering bugs, here’s how it all unfolded.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;1. Choosing the Testing Framework&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;For this project, I chose &lt;strong&gt;Google Test (GTest)&lt;/strong&gt; and &lt;strong&gt;Google Mock (GMock)&lt;/strong&gt; as my testing framework. These tools are the gold standard in the C++ world for writing unit tests and mocking dependencies.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Why GTest and GMock?&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;GTest provides a simple and powerful framework for writing tests with descriptive assertions.&lt;/li&gt;
&lt;li&gt;GMock enables mocking of external dependencies, which is crucial for testing interactions with APIs or other services.&lt;/li&gt;
&lt;li&gt;Both are well-documented and actively maintained, with a vibrant community for support.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;&lt;strong&gt;Links&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/google/googletest" rel="noopener noreferrer"&gt;Google Test&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/google/googletest" rel="noopener noreferrer"&gt;Google Mock&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;2. Setting Up the Framework&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Setting up GTest and GMock in my project involved the following steps:&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Installing GTest and GMock&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Linux&lt;/strong&gt;:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;  &lt;span class="nb"&gt;sudo &lt;/span&gt;apt-get &lt;span class="nb"&gt;install &lt;/span&gt;libgtest-dev
  &lt;span class="nb"&gt;cd&lt;/span&gt; /usr/src/gtest
  &lt;span class="nb"&gt;sudo &lt;/span&gt;cmake &lt;span class="nb"&gt;.&lt;/span&gt;
  &lt;span class="nb"&gt;sudo &lt;/span&gt;make
  &lt;span class="nb"&gt;sudo cp&lt;/span&gt; &lt;span class="k"&gt;*&lt;/span&gt;.a /usr/lib
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Windows&lt;/strong&gt;: I downloaded the source code from GitHub and built the libraries using CMake.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Adding Tests&lt;/strong&gt;
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Created a &lt;code&gt;tests.cpp&lt;/code&gt; file to house all test cases.&lt;/li&gt;
&lt;li&gt;Linked GTest and GMock during compilation:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   g++ &lt;span class="nt"&gt;-std&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;c++17 &lt;span class="nt"&gt;-I&lt;/span&gt;&amp;lt;gtest-include-path&amp;gt; &lt;span class="nt"&gt;-I&lt;/span&gt;&amp;lt;project-include-path&amp;gt; tests.cpp &lt;span class="nt"&gt;-o&lt;/span&gt; tests &lt;span class="nt"&gt;-lgtest&lt;/span&gt; &lt;span class="nt"&gt;-lgmock&lt;/span&gt; &lt;span class="nt"&gt;-lpthread&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;strong&gt;Running Tests&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;After building, I ran the tests:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;./tests
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The output showed which tests passed or failed, with detailed information for debugging.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;3. Mocking LLM Responses&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;One of the challenges in this project was testing the interaction with an external Language Model (LLM) API. Since relying on a live API during testing is impractical, I mocked the responses using GMock.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Approach to Mocking&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;I created a &lt;code&gt;MockApiClient&lt;/code&gt; class that inherited from &lt;code&gt;api_client&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Using &lt;code&gt;MOCK_METHOD&lt;/code&gt;, I defined mock behaviors for the &lt;code&gt;make_api_call&lt;/code&gt; method.&lt;/li&gt;
&lt;li&gt;Example:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;  &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MockApiClient&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;api_client&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;public:&lt;/span&gt;
      &lt;span class="n"&gt;MOCK_METHOD&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;make_api_call&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;prompt&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;override&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;

  &lt;span class="n"&gt;TEST&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;MockApiClientTests&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;MockedApiResponse&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="n"&gt;MockApiClient&lt;/span&gt; &lt;span class="n"&gt;mockClient&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="n"&gt;EXPECT_CALL&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;mockClient&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;make_api_call&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
          &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WillOnce&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;testing&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Return&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;R"({"choices": [{"message": {"content": "Mock Response"}}]})"&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

      &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;mockClient&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;make_api_call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Test Prompt"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="n"&gt;EXPECT_EQ&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;R"({"choices": [{"message": {"content": "Mock Response"}}]})"&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 allowed me to simulate different API responses (e.g., success, errors) without making actual network calls.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;4. Learning Through Test Case Writing&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Writing tests was an enlightening experience, filled with both challenges and "aha!" moments. Here’s what I learned:&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Lessons Learned&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Testing Forces Better Code&lt;/strong&gt;:&lt;br&gt;
Writing tests made me realize areas where my code was tightly coupled or lacked error handling. Refactoring for testability improved the overall design.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Mocking Simplifies Complex Testing&lt;/strong&gt;:&lt;br&gt;
Mocking external dependencies like the LLM API allowed me to focus on testing my code rather than external services.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Challenges and "Aha!" Moments&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Initially, setting up Google Mock felt intimidating due to its many features. However, once I understood the syntax, it became straightforward and incredibly powerful.&lt;/li&gt;
&lt;li&gt;I realized the importance of edge cases—what happens when the API returns an unexpected JSON format? This led to more robust parsing logic.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;5. Bugs and Edge Cases&lt;/strong&gt;
&lt;/h2&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Bugs Uncovered&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Empty Environment Variables&lt;/strong&gt;:&lt;br&gt;
A missing &lt;code&gt;API_KEY&lt;/code&gt; or &lt;code&gt;API_URL&lt;/code&gt; caused runtime errors. Adding unit tests for these scenarios led to meaningful error messages instead of crashes.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Invalid API Responses&lt;/strong&gt;:&lt;br&gt;
Parsing logic failed on API responses missing the &lt;code&gt;choices&lt;/code&gt; field. Tests caught this, prompting me to add error handling.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Edge Cases&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Responses with empty or malformed JSON.&lt;/li&gt;
&lt;li&gt;Unexpected data types in the JSON response (e.g., &lt;code&gt;choices&lt;/code&gt; being a string instead of an array).&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;6. Reflections and Future Plans&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;This lab reinforced the value of testing in software development. Before this project, I had limited experience with formal testing frameworks. Now, I feel confident in my ability to write meaningful test cases and mock external dependencies.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Future Testing Plans&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Continuous Integration&lt;/strong&gt;: I plan to integrate automated testing into a CI/CD pipeline using GitHub Actions.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Code Coverage&lt;/strong&gt;: Analyzing code coverage will ensure all critical paths are tested.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;More Mocks&lt;/strong&gt;: Expanding mocks to simulate other parts of the system.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;Conclusion&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Automated testing is not just about catching bugs—it's a mindset shift that promotes better design and maintainability. Tools like GTest and GMock make testing in C++ approachable and effective. This lab was a fantastic opportunity to sharpen my testing skills, and I’m excited to apply these practices to future projects.&lt;/p&gt;

&lt;p&gt;If you're working on a project and haven't tried automated testing yet, I encourage you to start. Your future self (and your users) will thank you!&lt;/p&gt;




&lt;h3&gt;
  
  
  &lt;strong&gt;Your Thoughts?&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Have you used Google Test or similar frameworks in your projects? What challenges have you faced in testing? I’d love to hear about your experiences!&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Improving Documentation in Theoretica</title>
      <dc:creator>Fahad Ali Khan</dc:creator>
      <pubDate>Tue, 12 Nov 2024 03:23:47 +0000</pubDate>
      <link>https://dev.to/fahadalikhanca/improving-documentation-in-theoretica-3le0</link>
      <guid>https://dev.to/fahadalikhanca/improving-documentation-in-theoretica-3le0</guid>
      <description>&lt;p&gt;In my latest contribution to the open-source library &lt;a href="https://github.com/chaotic-society/theoretica" rel="noopener noreferrer"&gt;Theoretica&lt;/a&gt;, I tackled &lt;a href="https://github.com/chaotic-society/theoretica/issues/81" rel="noopener noreferrer"&gt;Issue #81&lt;/a&gt; focused on refining and enhancing the inline documentation for two central components: &lt;code&gt;mat&lt;/code&gt; (the matrix class) and &lt;code&gt;vec&lt;/code&gt; (the vector class). This issue was raised to improve the readability and usability of these classes, which are essential in mathematical computations and commonly used across various areas in the library. Proper documentation is key to making complex code accessible to other developers and contributors.&lt;/p&gt;

&lt;h2&gt;
  
  
  Issue Summary
&lt;/h2&gt;

&lt;p&gt;The main goal of the issue was to update and improve the existing documentation for &lt;code&gt;mat&lt;/code&gt; and &lt;code&gt;vec&lt;/code&gt; classes. This involved:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Adding clear, concise explanations for each function in both classes.&lt;/li&gt;
&lt;li&gt;Using consistent language and structure throughout.&lt;/li&gt;
&lt;li&gt;Removing redundancies and improving clarity, especially in cases where documentation was minimal or missing.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;For anyone unfamiliar with these classes, &lt;code&gt;mat&lt;/code&gt; represents an N x K matrix with templated types, while &lt;code&gt;vec&lt;/code&gt; represents an N-dimensional vector. Both classes support various mathematical operations, such as addition, subtraction, scalar multiplication, and vector transformations.&lt;/p&gt;

&lt;h2&gt;
  
  
  Preparation for the Fix
&lt;/h2&gt;

&lt;p&gt;Before diving into the documentation, I took time to thoroughly understand the structure of the &lt;code&gt;mat&lt;/code&gt; and &lt;code&gt;vec&lt;/code&gt; classes. This was essential because the codebase for these classes is quite extensive and contains advanced template programming techniques. Each function’s purpose, inputs, and outputs needed to be understood to accurately document them.&lt;/p&gt;

&lt;p&gt;One of the initial challenges was ensuring I had a local development environment set up to properly view, test, and verify changes. I cloned the repository, configured the project, and set up Doxygen to generate HTML documentation to visualize changes effectively.&lt;/p&gt;

&lt;h2&gt;
  
  
  Learning Curve
&lt;/h2&gt;

&lt;p&gt;Working on this documentation required understanding some complex aspects of C++ template programming. Since the library uses advanced C++ techniques such as templates, inline functions, and recursive function calls for implementing mathematical operations, I reviewed the theory and usage of these constructs to confidently write documentation that would be both accurate and clear for other developers.&lt;/p&gt;

&lt;p&gt;I also had to familiarize myself with Doxygen conventions, as these would be used to generate structured documentation for the library. Specifically, I focused on how to organize documentation comments effectively without using &lt;code&gt;@brief&lt;/code&gt; for this issue, as I aimed for a more descriptive style in line with the existing documentation.&lt;/p&gt;

&lt;h2&gt;
  
  
  Implementing the Documentation
&lt;/h2&gt;

&lt;p&gt;The documentation process involved updating each function’s comment to ensure it provided value to the reader. Here’s a breakdown of some key elements of the update:&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;mat&lt;/code&gt; Class Documentation
&lt;/h3&gt;

&lt;p&gt;In the &lt;code&gt;mat&lt;/code&gt; class, I documented functions that dealt with:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Matrix Operations&lt;/strong&gt;: Functions such as &lt;code&gt;operator+&lt;/code&gt;, &lt;code&gt;operator-&lt;/code&gt;, and &lt;code&gt;operator*&lt;/code&gt; which handle addition, subtraction, and multiplication of matrices and scalars.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Vector Transformation&lt;/strong&gt;: Methods like &lt;code&gt;transform&lt;/code&gt; and &lt;code&gt;cross&lt;/code&gt; that apply matrix transformations to vectors.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Iterator Support&lt;/strong&gt;: Functions like &lt;code&gt;begin&lt;/code&gt; and &lt;code&gt;end&lt;/code&gt; that enable iteration over matrix elements.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;For each function, I included a description of the operation, the expected input types, and the output. For example, the documentation for &lt;code&gt;transform&lt;/code&gt; reads as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="c1"&gt;/// Transforms a vector by applying this matrix to it. &lt;/span&gt;
&lt;span class="c1"&gt;/// @param v The vector to transform, whose size must match the matrix column count.&lt;/span&gt;
&lt;span class="c1"&gt;/// @return A new vector resulting from the transformation.&lt;/span&gt;
&lt;span class="c1"&gt;/// Raises an error if the vector size does not match the column count of the matrix.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;code&gt;vec&lt;/code&gt; Class Documentation
&lt;/h3&gt;

&lt;p&gt;For the &lt;code&gt;vec&lt;/code&gt; class, the focus was on:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Basic Vector Operations&lt;/strong&gt;: Addition, subtraction, and scalar multiplication functions.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Dot and Cross Products&lt;/strong&gt;: I documented the mathematical implications of these functions and how they are computed internally.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Normalization&lt;/strong&gt;: I clarified the purpose of the &lt;code&gt;normalize&lt;/code&gt; and &lt;code&gt;normalized&lt;/code&gt; functions and explained how they can be used to obtain unit vectors.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Here is an example of the &lt;code&gt;normalize&lt;/code&gt; function’s documentation:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="c1"&gt;/// Normalizes the vector in place, adjusting it to have a magnitude of 1.&lt;/span&gt;
&lt;span class="c1"&gt;/// This changes the vector’s direction without altering its direction.&lt;/span&gt;
&lt;span class="c1"&gt;/// Throws an error if the vector’s magnitude is zero.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Highlights of the Fix
&lt;/h2&gt;

&lt;p&gt;The &lt;a href="https://github.com/chaotic-society/theoretica/pull/92" rel="noopener noreferrer"&gt;Pull Request #92&lt;/a&gt; includes detailed comments on each function, designed to make Theoretica’s core classes more accessible to users. By structuring the comments consistently, I ensured that users would find it easier to understand both the functionality and usage of &lt;code&gt;mat&lt;/code&gt; and &lt;code&gt;vec&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;An interesting part of this PR was adding documentation for recursive functions like &lt;code&gt;make_vec&lt;/code&gt;, which constructs vectors from multiple elements by using variadic templates. I provided clear explanations for how each argument in the parameter pack is assigned to successive elements in the vector.&lt;/p&gt;

&lt;h2&gt;
  
  
  Challenges and Overcoming Obstacles
&lt;/h2&gt;

&lt;p&gt;The main challenge was understanding the nuances of each mathematical operation within the &lt;code&gt;mat&lt;/code&gt; and &lt;code&gt;vec&lt;/code&gt; classes. Each function had subtle requirements and constraints, especially when dealing with template parameters and generic data types. I overcame this by diving into each function’s implementation, running sample cases, and referencing C++ template programming guides.&lt;/p&gt;

&lt;p&gt;Additionally, understanding the project maintainer’s preferences around documentation style was crucial. For example, they preferred that &lt;code&gt;@brief&lt;/code&gt; not be used, so I adapted the documentation style to fit the existing codebase conventions.&lt;/p&gt;

&lt;h2&gt;
  
  
  Interaction with Project Maintainers
&lt;/h2&gt;

&lt;p&gt;Working with the project maintainers was smooth. They provided helpful feedback regarding documentation style preferences, which helped refine the PR. This feedback loop ensured that the final submission met the maintainers' standards.&lt;/p&gt;

&lt;h2&gt;
  
  
  Final Thoughts and Next Steps
&lt;/h2&gt;

&lt;p&gt;Working on this documentation update gave me valuable insights into advanced C++ programming and the importance of clear documentation in open-source projects. As next steps, I’d like to contribute more to Theoretica’s documentation efforts, potentially expanding documentation coverage across other classes and modules.&lt;/p&gt;

&lt;p&gt;You can view my contributions in &lt;a href="https://github.com/chaotic-society/theoretica/issues/81" rel="noopener noreferrer"&gt;Issue #81&lt;/a&gt; and &lt;a href="https://github.com/chaotic-society/theoretica/pull/92" rel="noopener noreferrer"&gt;Pull Request #92&lt;/a&gt;. If you're interested in contributing to Theoretica, there are plenty of opportunities for improving documentation and testing across the codebase, so consider jumping in!&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Enhancing the Shortlist Modal in Recruitify</title>
      <dc:creator>Fahad Ali Khan</dc:creator>
      <pubDate>Fri, 08 Nov 2024 23:24:31 +0000</pubDate>
      <link>https://dev.to/fahadalikhanca/enhancing-the-shortlist-modal-in-recruitify-28a3</link>
      <guid>https://dev.to/fahadalikhanca/enhancing-the-shortlist-modal-in-recruitify-28a3</guid>
      <description>&lt;h3&gt;
  
  
  Issue Overview
&lt;/h3&gt;

&lt;p&gt;I recently worked on an issue in the Recruitify project that focused on enhancing the appearance and usability of the &lt;strong&gt;Shortlist Modal&lt;/strong&gt;. The goal was to improve the user experience by updating the styling, layout, and visual effects within the modal. You can find the original issue here: &lt;a href="https://github.com/priyam-03/Recruitify/issues/41" rel="noopener noreferrer"&gt;Recruitify Issue #41&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  What Was the Issue About?
&lt;/h3&gt;

&lt;p&gt;The issue requested improvements to the modal's UI, specifically asking for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Consistent padding and spacing between elements&lt;/li&gt;
&lt;li&gt;Better button styling with hover effects&lt;/li&gt;
&lt;li&gt;Enhanced modal appearance with shadow/blur effects and rounded corners&lt;/li&gt;
&lt;li&gt;A more vibrant color scheme with high contrast&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The objective was to make the modal look cleaner and more accessible, while also improving its interactivity and focus.&lt;/p&gt;

&lt;h3&gt;
  
  
  Preparing for the Fix
&lt;/h3&gt;

&lt;p&gt;Before jumping into the fix, I needed to set up the Recruitify project on my local machine and ensure both the frontend and backend components were running smoothly. This involved configuring MongoDB, Redis, and other dependencies in &lt;code&gt;.env&lt;/code&gt; files. Setting up the project took a bit of time as I encountered some issues with MongoDB authentication and Redis connection, which I managed to resolve after a few trials.&lt;/p&gt;

&lt;h3&gt;
  
  
  Learning Requirements
&lt;/h3&gt;

&lt;p&gt;To complete this fix, I needed to:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Familiarize myself with Recruitify’s existing code structure, especially how modals were implemented.&lt;/li&gt;
&lt;li&gt;Understand CSS modules and how to create modular styling in React applications.&lt;/li&gt;
&lt;li&gt;Apply knowledge of UX/UI principles to improve accessibility and visual appeal.&lt;/li&gt;
&lt;li&gt;Learn about React Router for adding a test route (&lt;code&gt;/modal-sandbox&lt;/code&gt;) to easily access and test the modal changes.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Code Explanation and Fix
&lt;/h3&gt;

&lt;p&gt;The main changes were made in &lt;code&gt;modal.module.css&lt;/code&gt;, which styles the &lt;code&gt;ShortlistModal&lt;/code&gt; component. Here’s a breakdown of the improvements:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Overlay Styling&lt;/strong&gt;: 

&lt;ul&gt;
&lt;li&gt;I added a semi-transparent background overlay with a slight blur effect to make the modal stand out and provide a clearer focal point.
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;   &lt;span class="nc"&gt;.modalOverlay&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
     &lt;span class="nl"&gt;background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;rgba&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;0.7&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
     &lt;span class="py"&gt;backdrop-filter&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;blur&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;3px&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;ol&gt;
&lt;li&gt;
&lt;strong&gt;Modal Content Box&lt;/strong&gt;:

&lt;ul&gt;
&lt;li&gt;To give the modal a more professional look, I applied rounded corners, a subtle shadow, and a smooth fade-in animation. This makes the modal appear less rigid and more approachable.
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;   &lt;span class="nc"&gt;.modalContent&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
     &lt;span class="nl"&gt;background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#ffffff&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
     &lt;span class="nl"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;30px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
     &lt;span class="nl"&gt;border-radius&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;12px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
     &lt;span class="nl"&gt;box-shadow&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0px&lt;/span&gt; &lt;span class="m"&gt;8px&lt;/span&gt; &lt;span class="m"&gt;16px&lt;/span&gt; &lt;span class="n"&gt;rgba&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;0.3&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
     &lt;span class="nl"&gt;animation&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;fadeIn&lt;/span&gt; &lt;span class="m"&gt;0.3s&lt;/span&gt; &lt;span class="n"&gt;ease&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;ol&gt;
&lt;li&gt;
&lt;strong&gt;Button Styling&lt;/strong&gt;:

&lt;ul&gt;
&lt;li&gt;The "Submit" button was given a vibrant blue color, while the "Cancel" button was styled with a soft grey. Hover effects were added to make the buttons more interactive, scaling them up slightly when hovered.
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;   &lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nt"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;"submit"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
     &lt;span class="nl"&gt;background-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#4A90E2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
     &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#ffffff&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
   &lt;span class="p"&gt;}&lt;/span&gt;
   &lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nt"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;"button"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
     &lt;span class="nl"&gt;background-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#CCCCCC&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
     &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#333333&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;ol&gt;
&lt;li&gt;
&lt;strong&gt;Input Field&lt;/strong&gt;:

&lt;ul&gt;
&lt;li&gt;I styled the input field with consistent padding, a soft border, and a focus effect. This makes it more accessible and visually pleasing.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Before and After
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Before:
&lt;/h4&gt;

&lt;p&gt;The modal had minimal styling, with no shadow or rounded corners. Buttons lacked hover effects, and the overall look was plain.&lt;/p&gt;

&lt;h4&gt;
  
  
  After:
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Consistent spacing&lt;/strong&gt; between elements makes the layout cleaner.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Shadow and rounded corners&lt;/strong&gt; give the modal a polished look.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Button hover effects&lt;/strong&gt; improve interactivity.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Color scheme&lt;/strong&gt; enhances accessibility, with vibrant colors and good contrast.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Research and Challenges
&lt;/h3&gt;

&lt;p&gt;I did some research on modal accessibility, specifically how to create a visually appealing modal that remains functional and accessible. I also reviewed CSS best practices for animations and hover effects.&lt;/p&gt;

&lt;p&gt;The biggest challenge was configuring the Recruitify project locally, as it required connecting to both MongoDB and Redis services. MongoDB’s authentication errors initially prevented me from running the backend, but I resolved this by checking the database credentials and permissions.&lt;/p&gt;

&lt;p&gt;Another challenge was ensuring the modal looked good across different screen sizes. I added responsive adjustments and tested the modal on various devices.&lt;/p&gt;

&lt;h3&gt;
  
  
  Interaction with Project Maintainers
&lt;/h3&gt;

&lt;p&gt;Since I was delayed in responding to the issue due to midterms, I posted an update apologizing for the delay and notifying the maintainer about my PR. They were understanding and provided positive feedback on my progress.&lt;/p&gt;

&lt;h3&gt;
  
  
  Difficulties and Solutions
&lt;/h3&gt;

&lt;p&gt;The most difficult part was configuring the project environment to run smoothly. By reading MongoDB and Redis documentation and experimenting with different configurations, I was able to resolve the issues. I also added a test route (&lt;code&gt;/modal-sandbox&lt;/code&gt;) to make it easier to access the modal without needing the full backend setup.&lt;/p&gt;

&lt;h3&gt;
  
  
  Link to Pull Request
&lt;/h3&gt;

&lt;p&gt;Here’s the link to my pull request, which contains the updated modal styling: &lt;a href="https://github.com/priyam-03/Recruitify/pull/67" rel="noopener noreferrer"&gt;Recruitify PR #67&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;Overall, this issue helped me improve my CSS skills and learn about modal accessibility. It was a valuable experience, and I’m looking forward to making more contributions in the future!&lt;/p&gt;

</description>
    </item>
  </channel>
</rss>
