A modern, production-ready, static React landing page template built with Vite, TailwindCSS, and Framer Motion. Features a fully integrated feedback widget powered by Next.js, Prisma, and Vercel. This project demonstrates best practices for building, styling, and extending React apps with real-world features.
Live Demo: https://embedded-marketing.netlify.app/
Feedback Widget Repository: Embedded-Feedback-Collector-Widget--NextJS-FullStack
Feedback Widget Live URL: https://embedded-feedback.vercel.app/auth/signin
- Project Overview
- Features
- Technology Stack
- Prerequisites
- Installation & Setup
- Running the Project
- Project Structure
- Components Documentation
- Animation System
- Feedback Widget Integration
- Environment Variables & Configuration
- Styling with TailwindCSS
- Building for Production
- Deployment
- Reusing Components
- API Endpoints & Routes
- How the Application Works
- Code Examples
- Keywords & Topics
- Troubleshooting
- Contributing
- Conclusion
This project is a static marketing landing page built with modern React practices. It serves as both a production-ready template and an educational resource for learning:
- React 18 with functional components and hooks
- Vite for fast development and optimized builds
- TailwindCSS for utility-first styling
- Framer Motion for smooth animations
- Component-based architecture for reusability
- Responsive design principles
- SEO optimization with meta tags
The landing page includes multiple sections: navigation, hero, services, banners, feature cards, and a newsletter signup. Additionally, it integrates an external feedback widget that can collect user feedback in real-time.
- ⚡ Fast Development: Built with Vite for instant HMR (Hot Module Replacement)
- 🎨 Beautiful UI: Modern design with TailwindCSS and custom styling
- 📱 Fully Responsive: Mobile-first approach with breakpoints for all devices
- 🎭 Smooth Animations: Scroll-triggered and entrance animations with Framer Motion
- 📝 Feedback Widget: Integrated feedback collection system
- 🔍 SEO Optimized: Comprehensive meta tags and semantic HTML
- 🚀 Production Ready: Optimized builds and deployment configuration
- ♿ Accessible: Semantic HTML and ARIA-friendly structure
- Navbar: Responsive navigation with mobile menu
- Hero Section: Eye-catching hero with CTA buttons
- Services: Grid-based service showcase
- Banners: Promotional sections with varied layouts
- Cards: Feature cards with icons and descriptions
- Newsletter: Email signup with social media links
- React 18.3.1 - UI library with hooks and functional components
- Vite 5.4.1 - Next-generation frontend build tool
- React DOM 18.3.1 - React rendering for web
- TailwindCSS 3.4.12 - Utility-first CSS framework
- PostCSS 8.4.47 - CSS processing tool
- Autoprefixer 10.4.20 - Automatic vendor prefixing
- Framer Motion 11.5.5 - Production-ready motion library for React
- React Icons 5.3.0 - Popular icon library (Font Awesome, etc.)
- ESLint 9.9.0 - Code linting and quality
- TypeScript Types - Type definitions for React
- Netlify - Frontend hosting and deployment
- Vercel - Feedback widget backend hosting
Before you begin, ensure you have the following installed:
- Node.js >= 22.0.0 (Download here)
- npm (comes with Node.js) or yarn
- Git for version control
- A code editor (VS Code recommended)
node --version # Should be >= 22.0.0
npm --version # Should be >= 9.0.0git clone https://github.com/yourusername/embedded-marketing.git
cd embedded-marketingnpm installThis will install all required packages listed in package.json:
- React and React DOM
- Vite and plugins
- TailwindCSS and PostCSS
- Framer Motion
- React Icons
- ESLint and plugins
After installation, your project structure should look like this:
embedded-marketing/
├── node_modules/ # Installed dependencies
├── public/ # Static assets
├── src/ # Source code
│ ├── components/ # React components
│ ├── assets/ # Images and icons
│ ├── utility/ # Utility functions
│ ├── App.jsx # Main app component
│ ├── main.jsx # Entry point
│ └── index.css # Global styles
├── index.html # HTML template
├── package.json # Project configuration
├── vite.config.js # Vite configuration
├── tailwind.config.js # TailwindCSS configuration
└── README.md # This fileStart the development server with Hot Module Replacement (HMR):
npm run devThe application will be available at:
- Local: http://localhost:5173
- Network: Vite will display the network URL in the terminal
Features in Dev Mode:
- ⚡ Instant HMR - Changes reflect immediately
- 🔍 Source maps for debugging
- 📊 Build size analysis
- 🐛 Error overlay with stack traces
To preview the production build locally:
npm run build
npm run previewThis builds the project and serves it from the dist folder, simulating production.
Check code quality and style:
npm run lintembedded-marketing/
├── public/ # Public static assets
│ └── vite.svg # Favicon
│
├── src/ # Source code directory
│ ├── assets/ # Images and media files
│ │ ├── 1.png # Hero/Navbar logo
│ │ ├── 2.png # Services image
│ │ ├── 3.png # Banner image
│ │ ├── 4.png # Banner2 image
│ │ ├── 5.png # Email/Footer background
│ │ └── icon/ # Icon assets
│ │ ├── 1.png
│ │ ├── 2.png
│ │ └── 3.png
│ │
│ ├── components/ # React components
│ │ ├── Banner/
│ │ │ ├── Banner.jsx # First promotional banner
│ │ │ └── Banner2.jsx # Second promotional banner
│ │ ├── Cards/
│ │ │ └── Cards.jsx # Feature cards grid
│ │ ├── Email/
│ │ │ └── Email.jsx # Newsletter/Footer section
│ │ ├── Hero/
│ │ │ └── Hero.jsx # Hero section
│ │ ├── Navbar/
│ │ │ └── Navbar.jsx # Navigation bar
│ │ └── Services/
│ │ └── Services.jsx # Services showcase
│ │
│ ├── utility/ # Utility functions
│ │ └── animation.js # Framer Motion animation variants
│ │
│ ├── App.jsx # Main app component (composes all sections)
│ ├── main.jsx # Application entry point
│ └── index.css # Global styles and Tailwind imports
│
├── dist/ # Production build output (generated)
│
├── index.html # HTML template with SEO meta tags
├── package.json # Project dependencies and scripts
├── vite.config.js # Vite build configuration
├── tailwind.config.js # TailwindCSS theme configuration
├── postcss.config.js # PostCSS configuration
├── eslint.config.js # ESLint configuration
├── netlify.toml # Netlify deployment configuration
└── README.md # Project documentationAll components follow a consistent pattern:
- Functional components using React hooks
- Framer Motion for animations
- TailwindCSS for styling
- Props for customization (where applicable)
- Reusable and composable
Location: src/components/Navbar/Navbar.jsx
Purpose: Main navigation bar with logo, links, and CTA button.
Features:
- Responsive design (hidden menu on mobile)
- Animated entrance (slides from top)
- Logo and brand name
- Navigation links array
- CTA button
Usage:
import Navbar from "./components/Navbar/Navbar";
function App() {
return <Navbar />;
}Customization:
- Edit
NavbarLinksarray to change navigation items - Modify logo by replacing
Logoimport - Update brand name text
- Customize CTA button text
Location: src/components/Hero/Hero.jsx
Purpose: Main hero section with headline, description, and CTA.
Features:
- Two-column grid layout (text + image)
- Staggered text animations
- Responsive image sizing
- Slide-in image animation
Usage:
import Hero from "./components/Hero/Hero";
function App() {
return <Hero />;
}Animation Details:
- Headline:
slideUp(0.2)- 0.2s delay - Description:
slideUp(0.5)- 0.5s delay - Button:
slideUp(0.8)- 0.8s delay - Image: Custom slide from right animation
Location: src/components/Services/Services.jsx
Purpose: Displays services/features in a grid layout.
Features:
- Header with title and description
- Responsive grid (1 col mobile, 2 cols tablet+)
- Scroll-triggered animations (
whileInView) - Large featured image + service cards
Usage:
import Services from "./components/Services/Services";
function App() {
return <Services />;
}Animation Pattern:
- Header: Fade in on scroll
- Cards: Slide from right with staggered delays (0.2s, 0.4s, 0.6s, 0.8s)
Location: src/components/Banner/Banner.jsx
Purpose: First promotional banner section.
Features:
- Text content on left, image on right
- Design philosophy quote
- Two feature highlights
- Scale effect on image (125% on desktop)
Usage:
import Banner from "./components/Banner/Banner";
function App() {
return <Banner />;
}Location: src/components/Banner/Banner2.jsx
Purpose: Second promotional banner with reversed layout.
Features:
- Image on left, text on right (reversed from Banner)
- Testimonial-style content
- Different animation direction (slides from left)
Usage:
import Banner2 from "./components/Banner/Banner2";
function App() {
return <Banner2 />;
}Why Two Banners?
- Creates visual variety
- Demonstrates layout flexibility
- Shows different animation patterns
Location: src/components/Cards/Cards.jsx
Purpose: Feature cards in a grid layout.
Features:
- Three feature cards
- Responsive grid (1/2/3 columns)
- Icons with circular backgrounds
- Gray background section for contrast
Usage:
import Cards from "./components/Cards/Cards";
function App() {
return <Cards />;
}Card Structure:
- Icon (circular, black background)
- Title (uppercase, bold)
- Description text
- "Learn More" link
Location: src/components/Email/Email.jsx
Purpose: Newsletter signup and footer section.
Features:
- Background image overlay
- Newsletter CTA
- Social media icons (Facebook, Twitter, Instagram, LinkedIn)
- Scale animation on scroll
Usage:
import Email from "./components/Email/Email";
function App() {
return <Email />;
}Social Icons:
- Uses
react-iconslibrary - Font Awesome icons
- Easily customizable
This project uses Framer Motion for all animations. Animations are defined in src/utility/animation.js for reusability.
export const slideUp = (delay) => {
return {
initial: {
y: 50, // Start 50px below
opacity: 0, // Start invisible
},
animate: {
y: 0, // End at natural position
opacity: 1, // End visible
transition: {
duration: 0.5,
delay: delay,
},
},
};
};Usage:
<motion.div variants={slideUp(0.2)} initial="initial" animate="animate">
Content here
</motion.div>export const slideBottom = (delay) => {
return {
initial: {
y: -100, // Start 100px above
opacity: 0,
},
animate: {
y: 0,
opacity: 1,
transition: {
duration: 0.5,
delay: delay,
},
},
};
};-
Entrance Animations: Elements animate when component mounts
- Used in: Navbar, Hero
-
Scroll-Triggered Animations: Elements animate when scrolled into view
- Used in: Services, Banner, Banner2, Cards, Email
- Trigger:
whileInViewprop
-
Staggered Animations: Multiple elements animate sequentially
- Used in: Hero (text elements), Services (cards)
<motion.div
initial={{ opacity: 0, x: -100 }} // Start state
animate={{ opacity: 1, x: 0 }} // End state
transition={{ duration: 0.5, delay: 0.2 }}
>
Content
</motion.div>The feedback widget is an external component loaded from a Vercel deployment. It's integrated directly in index.html using UMD builds.
Located in index.html:
<!-- Load React and ReactDOM UMD builds for the widget -->
<script src="https://unpkg.com/react@18/umd/react.production.min.js"></script>
<script src="https://unpkg.com/react-dom@18/umd/react-dom.production.min.js"></script>
<!-- Include the widget script from production (Vercel) -->
<script src="https://embedded-feedback.vercel.app/widget.umd.js"></script>
<!-- Widget component with configuration -->
<my-widget
api-base="https://embedded-feedback.vercel.app/api/feedback"
api-key="1e61d9ba70b084b5f8291f2aa75e67d9"
></my-widget>- UMD Builds: React and ReactDOM are loaded from CDN (unpkg.com)
- Widget Script: Custom widget script from Vercel deployment
- Custom Element:
<my-widget>is a web component - API Configuration: Points to feedback API endpoint
To use your own feedback widget:
- Deploy the Feedback Widget project to Vercel
- Update the
api-baseattribute with your API URL - Update the
api-keywith your API key - Update the widget script
srcwith your widget URL
- Collects user feedback
- Star ratings
- Real-time submission
- Dashboard for viewing feedback (separate application)
This project does NOT require a .env file for the frontend. The feedback widget configuration is hardcoded in index.html for simplicity.
If you want to use environment variables (recommended for production), follow these steps:
Create a .env file in the root directory:
VITE_WIDGET_API_BASE=https://embedded-feedback.vercel.app/api/feedback
VITE_WIDGET_API_KEY=1e61d9ba70b084b5f8291f2aa75e67d9
VITE_WIDGET_SCRIPT_URL=https://embedded-feedback.vercel.app/widget.umd.jsImportant: In Vite, environment variables must be prefixed with VITE_ to be accessible in the browser.
Replace hardcoded values with environment variables:
<script src="${import.meta.env.VITE_WIDGET_SCRIPT_URL}"></script>
<my-widget
api-base="${import.meta.env.VITE_WIDGET_API_BASE}"
api-key="${import.meta.env.VITE_WIDGET_API_KEY}"
></my-widget>Note: Since index.html is static, you'll need to use a build plugin or inject variables during build.
Create a template file:
VITE_WIDGET_API_BASE=your_api_base_url
VITE_WIDGET_API_KEY=your_api_key
VITE_WIDGET_SCRIPT_URL=your_widget_script_urlEnsure .env is in .gitignore:
.env
.env.local
.env.production
If deploying to Netlify, add environment variables in:
- Netlify Dashboard → Site Settings → Environment Variables
TailwindCSS is configured in tailwind.config.js:
export default {
content: ["./index.html", "./src/**/*.{js,ts,jsx,tsx}"],
theme: {
extend: {
colors: {
primary: "#fdcd2d", // Custom yellow/gold color
},
fontFamily: {
sans: ["Roboto", "sans-serif"],
},
container: {
center: true,
padding: {
DEFAULT: "1rem",
sm: "2rem",
lg: "4rem",
xl: "5rem",
"2xl": "6rem",
},
},
},
},
plugins: [],
};Defined in src/index.css:
@layer components {
.primary-btn {
@apply bg-primary text-white py-2 px-4 rounded-lg shadow-sm hover:shadow-md;
}
}Usage:
<button className="primary-btn">Click Me</button>Tailwind uses mobile-first breakpoints:
sm:- 640px and upmd:- 768px and uplg:- 1024px and upxl:- 1280px and up2xl:- 1536px and up
Example:
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3">
{/* 1 column on mobile, 2 on tablet, 3 on desktop */}
</div>- Container:
<div className="container">- Centered, responsive padding - Grid:
grid grid-cols-1 md:grid-cols-2- Responsive grid - Flex:
flex justify-between items-center- Flexbox layouts - Spacing:
py-8,px-4,gap-4- Padding and gaps - Text:
text-4xl font-bold- Typography utilities
npm run buildThis command:
- Optimizes all assets
- Minifies JavaScript and CSS
- Tree-shakes unused code
- Generates production-ready files in
dist/folder
dist/
├── assets/
│ ├── index-[hash].js # Bundled JavaScript
│ ├── index-[hash].css # Bundled CSS
│ └── [image]-[hash].png # Optimized images
└── index.html # HTML with asset references
Vite automatically:
- Code splitting
- Asset optimization
- CSS minification
- JavaScript minification
- Source map generation (optional)
npm run build
npm run previewThis project is configured for Netlify deployment.
- Connect your GitHub repository to Netlify
- Netlify will detect
netlify.tomlconfiguration - Build settings are automatically configured
npm run build
# Upload the 'dist' folder to Netlifynetlify.toml:
[build]
command = "npm run build"
publish = "dist"
[build.environment]
NODE_VERSION = "22"
[[redirects]]
from = "/*"
to = "/index.html"
status = 200Redirects: All routes redirect to index.html for SPA routing (if you add routing later).
npm install -g vercel
vercel-
Install
gh-pages:npm install --save-dev gh-pages -
Add to
package.json:
{
"scripts": {
"deploy": "npm run build && gh-pages -d dist"
}
}- Run:
npm run deploy
All components are designed to be reusable. Here's how to use them in other projects:
Copy the component folder to your project:
# Example: Copying Navbar
cp -r src/components/Navbar /path/to/your/project/src/components/Ensure you have required dependencies:
npm install framer-motion react-iconsCopy animation utilities:
cp src/utility/animation.js /path/to/your/project/src/utility/Copy required images:
cp src/assets/1.png /path/to/your/project/src/assets/import Navbar from "./components/Navbar/Navbar";
function App() {
return (
<div>
<Navbar />
{/* Your other content */}
</div>
);
}// In Navbar.jsx, modify the NavbarLinks array:
const NavbarLinks = [
{
id: 1,
title: "Home",
link: "/",
},
{
id: 2,
title: "Products", // Changed from "Features"
link: "/products",
},
// Add more links...
];Update tailwind.config.js:
theme: {
extend: {
colors: {
primary: "#your-color", // Change primary color
},
},
}Follow the existing pattern:
import React from "react";
import { motion } from "framer-motion";
import { slideUp } from "../../utility/animation";
const MyComponent = () => {
return (
<motion.div
variants={slideUp(0.2)}
initial="initial"
animate="animate"
className="container py-12"
>
{/* Your content */}
</motion.div>
);
};
export default MyComponent;This is a static single-page application with no client-side routing. All content is rendered in App.jsx.
If you want to add routing, install React Router:
npm install react-router-domThen set up routes:
import { BrowserRouter, Routes, Route } from "react-router-dom";
import Home from "./pages/Home";
import About from "./pages/About";
function App() {
return (
<BrowserRouter>
<Routes>
<Route path="/" element={<Home />} />
<Route path="/about" element={<About />} />
</Routes>
</BrowserRouter>
);
}The feedback widget uses an external API:
- Base URL:
https://embedded-feedback.vercel.app/api/feedback - Method: POST (for submitting feedback)
- Authentication: API key required
API Endpoints (from widget backend):
POST /api/feedback- Submit feedbackGET /api/feedback- Retrieve feedback (with authentication)
Note: The API is hosted separately. See the Feedback Widget Repository for backend details.
-
Entry Point (
main.jsx):- Creates React root
- Renders
<App />component - Wraps in
<StrictMode>for development checks
-
App Component (
App.jsx):- Composes all page sections
- Renders in order: Navbar → Hero → Services → Banner → Cards → Banner2 → Email
-
Component Rendering:
- Each component is self-contained
- Uses Framer Motion for animations
- Styled with TailwindCSS
-
Feedback Widget:
- Loaded from external script in
index.html - Renders as custom web component
- Communicates with backend API
- Loaded from external script in
-
Development (
npm run dev):- Vite dev server starts
- HMR watches for changes
- Serves from memory (fast)
-
Production (
npm run build):- Vite bundles all code
- Optimizes assets
- Generates static files in
dist/
- Component Mount: Entrance animations trigger
- Scroll:
whileInViewanimations trigger when element enters viewport - Stagger: Delays create sequential animations
import React from "react";
import { motion } from "framer-motion";
import { slideUp } from "../utility/animation";
const NewSection = () => {
return (
<section className="container py-20">
<motion.h2
variants={slideUp(0.2)}
initial="initial"
whileInView="animate"
className="text-4xl font-bold text-center"
>
New Section Title
</motion.h2>
<motion.p
variants={slideUp(0.4)}
initial="initial"
whileInView="animate"
className="text-center mt-4"
>
Section description here.
</motion.p>
</section>
);
};
export default NewSection;import React from "react";
import { motion } from "framer-motion";
const CustomButton = ({ text, onClick, variant = "primary" }) => {
return (
<motion.button
whileHover={{ scale: 1.05 }}
whileTap={{ scale: 0.95 }}
onClick={onClick}
className={`primary-btn ${variant === "secondary" ? "bg-gray-600" : ""}`}
>
{text}
</motion.button>
);
};
export default CustomButton;import React from "react";
import { motion } from "framer-motion";
const ResponsiveImage = ({ src, alt }) => {
return (
<motion.img
initial={{ opacity: 0, scale: 0.8 }}
whileInView={{ opacity: 1, scale: 1 }}
transition={{ duration: 0.5 }}
src={src}
alt={alt}
className="w-full md:w-1/2 lg:w-1/3 mx-auto rounded-lg shadow-lg"
/>
);
};
export default ResponsiveImage;import React from "react";
import { motion } from "framer-motion";
import { slideUp } from "../utility/animation";
const FeatureList = ({ features }) => {
return (
<div className="grid grid-cols-1 md:grid-cols-3 gap-6">
{features.map((feature, index) => (
<motion.div
key={feature.id}
variants={slideUp(index * 0.1)}
initial="initial"
whileInView="animate"
className="p-6 bg-white rounded-lg shadow-md"
>
<h3 className="text-xl font-bold">{feature.title}</h3>
<p className="mt-2 text-gray-600">{feature.description}</p>
</motion.div>
))}
</div>
);
};
// Usage:
// const features = [
// { id: 1, title: "Feature 1", description: "Description 1" },
// { id: 2, title: "Feature 2", description: "Description 2" },
// ];
// <FeatureList features={features} />- React, React Hooks, Functional Components, JSX
- Vite, Build Tools, HMR, Module Bundling
- TailwindCSS, Utility-First CSS, Responsive Design
- Framer Motion, Animations, Motion Design
- Netlify, Vercel, Static Site Hosting, Deployment
- Component-Based Architecture, Reusability, Composition
- Responsive Web Design, Mobile-First, Breakpoints
- SEO Optimization, Meta Tags, Semantic HTML
- Performance Optimization, Code Splitting, Tree Shaking
- Web Components, UMD Builds, External Scripts
- Hot Module Replacement, Fast Refresh, Development Server
- ESLint, Code Quality, Linting
- Git, Version Control, GitHub
- npm, Package Management, Dependencies
- UI/UX Design, Landing Pages, Marketing Pages
- Animation, Transitions, Scroll Triggers
- Typography, Color Schemes, Spacing
- Accessibility, Semantic HTML, ARIA
Error: Port 5173 is already in use
Solution:
# Kill process on port 5173 (macOS/Linux)
lsof -ti:5173 | xargs kill -9
# Or use a different port
npm run dev -- --port 3000Error: Cannot find module 'framer-motion'
Solution:
npm installError: Styles not applying
Solution:
- Check
tailwind.config.jscontent paths - Ensure
@tailwinddirectives inindex.css - Restart dev server
Error: Build errors or warnings
Solution:
# Clear cache and rebuild
rm -rf node_modules dist
npm install
npm run buildError: Widget not appearing
Solution:
- Check browser console for errors
- Verify API URLs in
index.html - Ensure network connectivity
- Check CORS settings on API server
- Check Vite Documentation
- Check React Documentation
- Check TailwindCSS Documentation
- Check Framer Motion Documentation
Contributions are welcome! Here's how you can help:
- Fork the repository
- Create a feature branch:
git checkout -b feature/amazing-feature - Commit your changes:
git commit -m 'Add amazing feature' - Push to the branch:
git push origin feature/amazing-feature - Open a Pull Request
- Follow existing code style
- Add comments for complex logic
- Update README if adding features
- Test your changes thoroughly
- Ensure ESLint passes
This Embedded Marketing project is a comprehensive example of modern React development, showcasing:
- ✅ Best Practices: Component architecture, code organization, and styling patterns
- ✅ Modern Tools: Vite, TailwindCSS, Framer Motion for optimal developer experience
- ✅ Production Ready: Optimized builds, SEO, and deployment configurations
- ✅ Educational Value: Well-commented code and comprehensive documentation
- ✅ Reusability: Modular components that can be used in other projects
- ✅ Real-World Integration: External widget integration demonstrates practical patterns
Whether you're learning React, building a landing page, or looking for a template to start from, this project provides a solid foundation.
Key Takeaways:
- React 18 with functional components
- Vite for fast development
- TailwindCSS for rapid styling
- Framer Motion for smooth animations
- Component-based architecture
- Responsive design principles
- SEO optimization
- Production deployment
Feel free to use this project repository and extend this project further!
If you have any questions or want to share your work, reach out via GitHub or my portfolio at https://arnob-mahmud.vercel.app/.
Enjoy building and learning! 🚀
Thank you! 😊



