Slide 1 of 10

🌐 Building a Social Media Feed

Learn Vue.js, APIs, and Modern Web Development

Create an interactive social media feed that connects to a real API

What You'll Learn:

  • Why JavaScript frameworks make coding easier
  • What APIs are and how they work
  • How to install Node.js and create Vue apps
  • How to fetch data from an API with async/await
  • Build a working social media feed!

🚀 Why JavaScript Frameworks?

Think of Frameworks Like LEGO Kits!

Without a framework: You get a huge box of individual LEGO bricks. You have to figure everything out yourself!

With a framework: You get a LEGO kit with pre-built sections and instructions. Just snap things together!

🧱

Old Way (Vanilla JS)

Everything by hand

Slow and messy

🏗️

New Way (Frameworks)

Pre-built components

Fast and organized

Framework Benefits:

  • Save time: Don't reinvent the wheel
  • Stay organized: Everything has its place
  • Easy updates: Change one part, everything updates automatically
  • Big community: Millions of developers to help you
  • Best practices: Learn the right way from the start

🟢 Why Vue.js is Our Choice

Framework Who Makes It Learning Curve For Russian Users
React.js Facebook/Meta (USA) Medium ⚠️ Risk of sanctions/blocking
Angular Google (USA) Steep ⚠️ Risk of sanctions/blocking
Vue.js 🎯 Open Source Community 🌍 Gentle ✅ Safe & Independent

Vue.js Advantages:

  • Open source: Belongs to everyone, not one company
  • Gentle learning curve: Easy for beginners
  • Great documentation: Like having a helpful teacher
  • Single-file components: HTML + CSS + JavaScript together
  • Reactive: Automatic updates (magic!)

Choosing Vue is Like Choosing:

React/Angular: Renting a house - the owner (Meta/Google) can change rules or kick you out

Vue.js: Owning a house - it's yours forever, no one can take it away!

🤝 What is an API?

API = Restaurant Waiter

Think of an API like a waiter in a restaurant:

  • You (Browser): "I'd like posts from user 1" (places order)
  • API (Waiter): Takes your order to the kitchen
  • Database (Kitchen): Prepares the data
  • API (Waiter): Brings the data back to you
🌐

Your Vue App

"Give me posts!"

🤝

API

Messenger

💾

Database

Data storage

Our API: api.techshare.cc

We have a real API that serves data! Try these in your browser:

# See all posts: https://api.techshare.cc/api/posts # See all users: https://api.techshare.cc/api/users # See comments: https://api.techshare.cc/api/comments

Copy and paste these URLs in your browser to see the data!

📦 Step 1: Install Node.js

1
What is Node.js?

Think of Node.js as the engine that runs JavaScript on your computer!

Usually JavaScript only runs in browsers. Node.js lets it run on YOUR computer too!

2
Download and Install
  • Go to nodejs.org
  • Download the LTS version (Long Term Support = stable)
  • Run the installer
  • Click "Next" through everything
3
Check if it Works

Open PowerShell (Windows) or Terminal (Mac):

# Check Node.js version node --version # Should show: v20.x.x or v22.x.x # Check npm version npm --version # Should show: 10.x.x or higher
4
Windows Users - Fix Execution Policy

If PowerShell says "not allowed":

# Open PowerShell as Administrator # Type this: Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser

Type Y and press Enter when asked!

⚡ Step 2: Create Vue App with Vite

1
Open Terminal/PowerShell

Navigate to where you want your project:

cd Documents # or wherever you want your project
2
Create Vue App

Type this command (with double dash --):

# Create Vue app with Vite npm create vite@latest my-vue-app -- --template vue

Note: -- --template vue means two dashes, space, two dashes

3
Answer Prompts

You'll see questions - just press Enter for all:

✔ Project name: … my-vue-app ✔ Package name: … my-vue-app ✔ Add TypeScript? … No ✔ Add JSX Support? … No ✔ Add Vue Router? … No (or Yes if you want pages) ✔ Add Pinia? … No (or Yes for state management) ✔ Add Vitest? … No ✔ Add ESLint? … No (or Yes for code quality)
4
Navigate to your app
cd my-vue-app

🚀 Step 3: Install and Run

1
Install Dependencies

These are like "batteries" for your app:

npm install

Wait 1-2 minutes while it downloads everything

2
Start Development Server
npm run dev

You'll see:

VITE v5.x.x ready in xxx ms ➜ Local: http://localhost:5173/ ➜ Network: use --host to expose
3
Open in Browser

Copy and paste this in your browser:

http://localhost:5173
4
Explore the Default App
  • Click the count button - see it update!
  • Notice the Vue and Vite logos
  • This is your starting point

🗂️ Step 4: Understand Project Structure

Your project folder looks like this:

my-vue-app/ # Your project house ├── node_modules/ # Toolbox (don't touch!) ├── public/ # Front yard │ └── vite.svg # Vite logo ├── src/ # Main house │ ├── assets/ # Pictures & decorations │ │ └── vue.svg # Vue logo │ ├── components/ # Furniture │ │ └── HelloWorld.vue # Example furniture │ ├── App.vue # Living room (main area) │ └── main.js # Front door (starts app) ├── index.html # Land plot ├── package.json # Shopping list └── vite.config.js # House blueprints

Important Files:

  • src/App.vue: Main component - we'll replace this
  • src/main.js: Starts the Vue app
  • index.html: Main HTML file
  • package.json: Lists all tools we use

Stop and Restart Server:

In your terminal where npm run dev is running:

# Press Ctrl + C to stop # Then restart: npm run dev

🎨 Step 5: Create Social Media Feed

1
Open App.vue

Navigate to: my-vue-app/src/App.vue

Open it in your code editor (VS Code, Notepad++, etc.)

2
Delete Everything

Select all code in App.vue and delete it

3
Paste Our Social Feed Code

Copy and paste this complete code:

<template> <div class="social-feed"> <!-- Header --> <header class="header"> <h1>📱 Social Media Feed</h1> <p class="subtitle">Simple feed using Async/Await</p> </header> <!-- Main Feed --> <main class="feed"> <!-- Stats --> <div class="stats"> <p>Total posts: {{ posts.length }}</p> <button @click="loadPosts" :disabled="loading" class="refresh-btn"> {{ loading ? '🔄 Loading...' : '🔄 Refresh' }} </button> </div> <!-- Loading --> <div v-if="loading" class="loading"> <div class="spinner"></div> <p>Loading posts...</p> </div> <!-- Error --> <div v-else-if="error" class="error"> <p>❌ Error: {{ error }}</p> <button @click="loadPosts" class="retry-btn">Try Again</button> </div> <!-- Posts --> <div v-else class="posts"> <div v-if="posts.length === 0" class="empty"> <p>No posts available.</p> </div> <div v-else class="posts-list"> <div v-for="post in posts" :key="post._id || post.id" class="post" > <!-- User info --> <div class="user-info"> <div class="avatar">U{{ post.userId }}</div> <div> <h3>User {{ post.userId }}</h3> <small>Post ID: {{ (post._id || post.id).substring(0, 10) }}...</small> </div> </div> <!-- Post content --> <div class="post-content"> <h4>{{ post.title }}</h4> <p>{{ post.body || post.content }}</p> </div> </div> </div> </div> </main> <!-- Footer --> <footer class="footer"> <p>API: https://api.techshare.cc/api/posts</p> </footer> </div> </template> <script setup> import { ref, onMounted } from 'vue' // State const posts = ref([]) const loading = ref(false) const error = ref(null) // Load posts function async function loadPosts() { loading.value = true error.value = null try { console.log('Fetching posts...') const response = await fetch('https://api.techshare.cc/api/posts') if (!response.ok) { throw new Error(`Failed to fetch: ${response.status}`) } posts.value = await response.json() console.log(`Loaded ${posts.value.length} posts`) } catch (err) { console.error('Error:', err) error.value = err.message || 'Something went wrong' } finally { loading.value = false } } // Load on page load onMounted(() => { loadPosts() }) </script> <style scoped> * { margin: 0; padding: 0; box-sizing: border-box; } .social-feed { min-height: 100vh; background: #f5f7fa; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; } /* Header */ .header { background: white; padding: 2rem; text-align: center; border-bottom: 1px solid #eaeaea; } .header h1 { color: #333; font-size: 2rem; margin-bottom: 0.5rem; } .subtitle { color: #666; font-size: 1rem; } /* Feed */ .feed { max-width: 800px; margin: 0 auto; padding: 2rem; } /* Stats */ .stats { display: flex; justify-content: space-between; align-items: center; margin-bottom: 2rem; padding: 1rem; background: white; border-radius: 8px; box-shadow: 0 1px 3px rgba(0,0,0,0.1); } .stats p { font-weight: 600; color: #333; } .refresh-btn { padding: 0.5rem 1rem; background: #4361ee; color: white; border: none; border-radius: 4px; cursor: pointer; font-weight: 500; } .refresh-btn:disabled { opacity: 0.5; cursor: not-allowed; } /* Loading */ .loading { text-align: center; padding: 3rem; } .spinner { width: 40px; height: 40px; border: 3px solid #ddd; border-top: 3px solid #4361ee; border-radius: 50%; margin: 0 auto 1rem; animation: spin 1s linear infinite; } @keyframes spin { 0% { transform: rotate(0deg); } 100% { transform: rotate(360deg); } } /* Error */ .error { text-align: center; padding: 2rem; background: #ffebee; color: #c62828; border-radius: 8px; margin-bottom: 1rem; } .retry-btn { margin-top: 1rem; padding: 0.5rem 1.5rem; background: #c62828; color: white; border: none; border-radius: 4px; cursor: pointer; } /* Empty */ .empty { text-align: center; padding: 3rem; color: #666; } /* Posts list */ .posts-list { display: flex; flex-direction: column; gap: 1.5rem; } /* Single post */ .post { background: white; border-radius: 12px; padding: 1.5rem; box-shadow: 0 2px 8px rgba(0,0,0,0.08); } /* User info */ .user-info { display: flex; align-items: center; gap: 1rem; margin-bottom: 1rem; padding-bottom: 1rem; border-bottom: 1px solid #f0f0f0; } .avatar { width: 50px; height: 50px; background: #4361ee; border-radius: 50%; display: flex; align-items: center; justify-content: center; color: white; font-weight: bold; font-size: 1.2rem; } .user-info h3 { color: #333; margin-bottom: 0.25rem; } .user-info small { color: #888; font-size: 0.85rem; } /* Post content */ .post-content h4 { color: #333; margin-bottom: 0.75rem; font-size: 1.1rem; line-height: 1.4; } .post-content p { color: #555; line-height: 1.6; font-size: 0.95rem; } /* Footer */ .footer { text-align: center; padding: 2rem; color: #666; font-size: 0.9rem; border-top: 1px solid #eaeaea; margin-top: 3rem; } /* Responsive */ @media (max-width: 768px) { .header { padding: 1.5rem; } .header h1 { font-size: 1.5rem; } .feed { padding: 1rem; } .stats { flex-direction: column; gap: 1rem; text-align: center; } .post { padding: 1rem; } .user-info { gap: 0.75rem; } .avatar { width: 40px; height: 40px; font-size: 1rem; } } </style>

🎉 Step 6: See the Magic Happen!

1
Save App.vue

Save the file (Ctrl + S or Cmd + S)

2
Check Your Browser

Go to http://localhost:5173

You should see:

  • A beautiful social media feed header
  • Posts loading from the API
  • Real data from api.techshare.cc
  • A refresh button to get new data

What Just Happened? Magic!

🌐

Your Vue App

Said "give me posts"

🤝

API

Messenger delivered

💾

Database

Gave real data

Async/Await = Super Fast Messenger

async function loadPosts(): "I'll do this job, but I might need to wait"

await fetch(): "Wait here until you get the data"

.then() vs async/await: Phone call vs text message!

🎓 What You've Accomplished:

  • ✅ Learned why frameworks save time
  • ✅ Chose Vue.js (safe open source option)
  • ✅ Installed Node.js and npm
  • ✅ Created a Vue app with Vite
  • ✅ Connected to a real API
  • ✅ Built a working social media feed!