Today, I made some exciting progress on my X Clone project, and I wanted to share the updates with you all, Below is a complete project that includes the steps to set up a simple X Clone project with backend authentication, frontend login/posting functionality, and Google OAuth using Node.js with Express, MongoDB for database, and Google OAuth for login.
I’ll walk you through the steps to set up the project with RUM (React, Node.js, MongoDB) along with code to get started.
Project Setup: X Clone
Backend Setup (Node.js + Express + MongoDB)
Initialize Node.js project
codemkdir x-clone
cd x-clone
npm init -y
Install Required Dependencies
- Express for the server
- Mongoose for MongoDB interactions
- Passport for authentication
- Google OAuth 2.0 for login
- Bcryptjs for password hashing
- JWT for token-based authentication
codenpm install express mongoose passport passport-google-oauth20 bcryptjs jsonwebtoken dotenv
Create the Backend File Structure
codex-clone/
├── server.js
├── .env
├── models/
│ └── User.js
├── routes/
│ └── authRoutes.js
└── config/
└── passport.js
Backend Code
server.js
codeconst express = require('express');
const mongoose = require('mongoose');
const passport = require('passport');
const dotenv = require('dotenv');
const authRoutes = require('./routes/authRoutes');
// Load environment variables
dotenv.config();
// Initialize Express app
const app = express();
app.use(express.json());
// MongoDB connection
mongoose.connect(process.env.MONGODB_URI, { useNewUrlParser: true, useUnifiedTopology: true })
.then(() => console.log('MongoDB connected'))
.catch(err => console.log(err));
// Passport middleware
app.use(passport.initialize());
// Routes
app.use('/api/auth', authRoutes);
// Server listening
const PORT = process.env.PORT || 5000;
app.listen(PORT, () => console.log(`Server running on port ${PORT}`));
config/passport.js
codeconst passport = require('passport');
const GoogleStrategy = require('passport-google-oauth20').Strategy;
const User = require('../models/User');
// Set up Google OAuth strategy
passport.use(new GoogleStrategy({
clientID: process.env.GOOGLE_CLIENT_ID,
clientSecret: process.env.GOOGLE_CLIENT_SECRET,
callbackURL: process.env.GOOGLE_CALLBACK_URL
}, async (accessToken, refreshToken, profile, done) => {
try {
const existingUser = await User.findOne({ googleId: profile.id });
if (existingUser) {
return done(null, existingUser);
}
const newUser = new User({
googleId: profile.id,
name: profile.displayName,
email: profile.emails[0].value
});
await newUser.save();
return done(null, newUser);
} catch (err) {
return done(err, null);
}
}));
passport.serializeUser((user, done) => {
done(null, user.id);
});
passport.deserializeUser((id, done) => {
User.findById(id, (err, user) => {
done(err, user);
});
});
models/User.js
codeconst mongoose = require('mongoose');
const userSchema = new mongoose.Schema({
googleId: { type: String, required: true },
name: { type: String, required: true },
email: { type: String, required: true },
});
module.exports = mongoose.model('User', userSchema);
routes/authRoutes.js
codeconst express = require('express');
const passport = require('passport');
const router = express.Router();
// Google OAuth login route
router.get('/google', passport.authenticate('google', {
scope: ['profile', 'email']
}));
// Google OAuth callback route
router.get('/google/callback', passport.authenticate('google', { failureRedirect: '/' }),
(req, res) => {
res.redirect('/');
}
);
// Logout route
router.get('/logout', (req, res) => {
req.logout();
res.redirect('/');
});
module.exports = router;
.env
File (add your credentials)
codeMONGODB_URI=mongodb://localhost:27017/x-clone
GOOGLE_CLIENT_ID=your-google-client-id
GOOGLE_CLIENT_SECRET=your-google-client-secret
GOOGLE_CALLBACK_URL=http://localhost:5000/api/auth/google/callback
JWT_SECRET=your-secret-key
Frontend Setup (React)
Create a React app
codenpx create-react-app x-clone-client
cd x-clone-client
Install Axios for API calls
codenpm install axios react-router-dom
Create the Frontend File Structure
codex-clone-client/
├── src/
│ ├── components/
│ │ └── Auth.js
│ ├── App.js
│ └── index.js
└── .env
Frontend Code
src/App.js
codeimport React, { useState } from 'react';
import { BrowserRouter as Router, Route, Switch } from 'react-router-dom';
import axios from 'axios';
import Auth from './components/Auth';
function App() {
const [isAuthenticated, setIsAuthenticated] = useState(false);
// Check authentication on load
React.useEffect(() => {
axios.get('/api/auth/status')
.then(response => setIsAuthenticated(response.data.isAuthenticated))
.catch(err => console.log(err));
}, []);
return (
<Router>
<div className="App">
<Switch>
<Route path="/" exact>
{isAuthenticated ? (
<h1>Welcome to X Clone</h1>
) : (
<Auth setIsAuthenticated={setIsAuthenticated} />
)}
</Route>
</Switch>
</div>
</Router>
);
}
export default App;
src/components/Auth.js
codeimport React from 'react';
import axios from 'axios';
const Auth = ({ setIsAuthenticated }) => {
const handleGoogleLogin = () => {
window.location.href = '/api/auth/google';
};
return (
<div>
<button onClick={handleGoogleLogin}>Login with Google</button>
</div>
);
};
export default Auth;
src/index.js
codeimport React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
ReactDOM.render(<App />, document.getElementById('root'));
Running the Project
Start the Backend Server: In your x-clone directory:
codenode server.js
Start the Frontend React App: In your x-clone-client directory:
npm start
Now, when you navigate to http://localhost:3000/
, you’ll be able to log in using Google OAuth, and after successful login, you’ll see a welcome message.
Conclusion
This project covers a simple X Clone with Google OAuth authentication, login functionality, and a basic user dashboard. It leverages Node.js, Express, MongoDB, React, and Google OAuth 2.0 for login.
As you continue developing this app, consider adding more features like user profiles, posting functionality, or real-time updates to match the capabilities of a platform like X.