A modern, production-ready Next.js application demonstrating server-side streaming with React Suspense, showcasing popular web frameworks and development tools.
- β‘ Server-Side Streaming - Leverages Next.js 15+ streaming with Suspense boundaries for optimal performance
- π― Framework Showcase - Displays 9 popular frameworks (React, Vue, Angular, Svelte, Preact, Angular, Astro, Flutter, Solid)
- πΎ Persistent Likes - Save your favorite frameworks to browser storage with instant visual feedback
- π¨ Modern UI - Built with shadcn/ui and Tailwind CSS for a polished, responsive design
- βΏ Accessible - Full ARIA support, keyboard navigation, and semantic HTML
- π Type Safe - JavaScript with clear component structure and error handling
- Memoized components to prevent unnecessary re-renders
- Optimized key props for stable React rendering
- Centralized icon data storage for reduced memory usage
- Image optimization with AVIF and WebP formats
- Automatic code splitting and lazy loading with Suspense
- Optimistic Updates - Like buttons provide instant feedback using React's
useOptimistichook - Error Boundaries - Graceful error handling with recovery options
- Skeleton Loaders - Beautiful loading states while content streams in
- SEO Optimized - Rich metadata, proper heading hierarchy, and schema markup support
| Technology | Version | Purpose |
|---|---|---|
| Next.js | 15.4.4 | React framework with streaming support |
| React | 19.1.0 | UI library |
| Tailwind CSS | 4 | Utility-first CSS framework |
| Lucide React | 0.525.0 | Icon library |
| Radix UI | 1.2.3 | Accessible component primitives |
- Node.js 18.0 or higher
- npm 9.0+ or yarn 4.0+
# Clone the repository
git clone https://github.com/Antonynans/Next.js-streaming-demo.git
cd nextjs-streaming
# Install dependencies
npm install
# or
yarn install# Start development server with Turbopack
npm run devThe application will be available at http://localhost:3000 (or the next available port if 3000 is in use).
# Build for production
npm run build
# Start production server
npm start# Run ESLint
npm run lintnextjs-streaming/
βββ app/
β βββ globals.css # Global styles
β βββ layout.js # Root layout with metadata
β βββ page.js # Home page
β βββ streaming-demo/
β βββ page.js # Streaming demo page
βββ components/
β βββ error-boundary.js # Error handling component
β βββ icon-card.js # Individual tool card
β βββ icon-component.js # Icon renderer
β βββ like-button.js # Like button with persistence
β βββ tools-cards.js # Main tools container
β βββ tools-cards-view.js # Client-side tools view
β βββ tools-cards-wrapper.js # Filter wrapper
β βββ tools-filter.js # Search and sort UI
β βββ ui/ # shadcn/ui components
β βββ button.jsx
β βββ card.jsx
β βββ card-skeleton.jsx
β βββ skeleton.jsx
βββ lib/
β βββ getTools.js # Server action for fetching tools
β βββ icons-data.js # Centralized icon definitions
β βββ utils.js # Utility functions
βββ next.config.mjs # Next.js configuration
βββ postcss.config.mjs # PostCSS configuration
βββ tailwind.config.js # Tailwind CSS configuration
βββ package.json # Dependencies and scripts
The main entry point that:
- Fetches tools data server-side using a server action
- Wraps individual cards with Suspense boundaries
- Handles errors gracefully
- Displays skeleton loaders while streaming
// Components render individually as they stream in
<Suspense fallback={<CardSkeleton />}>
<ToolsCard toolPromise={toolPromise} />
</Suspense>Demonstrates advanced React patterns:
- Uses
useOptimisticfor instant UI feedback - Persists data to localStorage
- Handles hydration safely with
useEffect - Provides proper ARIA labels
Renders framework icons from centralized data store, enabling:
- Better code organization
- Reduced memory usage
- Easy maintenance and updates
The application uses Next.js 15+ streaming capabilities to progressively render content:
- Server Components render on the server
- Suspense Boundaries stream content as it's ready
- Fallback UI shows skeleton loaders
- Client Interactivity works immediately on hydration
The like button demonstrates React 19's useOptimistic hook:
const [optimisticLiked, addOptimisticLike] = useOptimistic(false);
// Immediate UI update while server processes
addOptimisticLike(!optimisticLiked);
// Server updates localStorage in background
await toggleLike(toolId, optimisticLiked);Multiple layers of error handling:
- Server-side validation in
getTools() - Error boundary component for React errors
- Graceful fallbacks for missing data
- User-friendly error messages
- Code Splitting: Automatic chunking of JavaScript
- Lazy Loading: Components load on-demand with Suspense
- Image Optimization: Configured AVIF and WebP formats
- Memoization: Prevents unnecessary re-renders with
React.memo - Hydration Safety: Proper hydration handling for client/server mismatches
- ARIA Labels: All interactive elements have proper labels
- Keyboard Navigation: Full keyboard support
- Semantic HTML: Proper heading hierarchy and structure
- Screen Reader Support: Enhanced with descriptive labels
- Color Contrast: WCAG AA compliant
- Security Headers: X-UA-Compatible and X-Content-Type-Options configured
- Content Security: Protected against XSS attacks
- Input Validation: Server-side validation of all data
- Secure Defaults: Safe configuration in next.config.mjs
- Chrome/Edge 90+
- Firefox 88+
- Safari 14+
- Mobile browsers (iOS Safari, Chrome Mobile)
# Run linter
npm run lint
# Build for production (validates entire app)
npm run buildCurrently, no environment variables are required. The app uses:
NEXT_PUBLIC_*- Client-side accessible variables (none currently)- Server-side only variables - None configured
To add environment variables, create .env.local:
# Example (if needed in future)
NEXT_PUBLIC_API_URL=https://api.example.com# Deploy to Vercel (connected GitHub repo)
vercel# Build Docker image
docker build -t nextjs-streaming .
# Run container
docker run -p 3000:3000 nextjs-streamingThe app works on any platform supporting Node.js 18+:
- Netlify
- AWS Amplify
- Railway
- Render
- DigitalOcean
- Server Components - Render on server, zero JavaScript cost
- Suspense & Streaming - Progressive enhancement of UI
- useOptimistic - React 19 feature for optimistic updates
- Error Boundaries - Graceful error handling
- Client vs Server - Clear separation of concerns
- Performance Optimization - Memoization and code splitting
npm run dev # Start development server with Turbopack
npm run build # Build for production
npm start # Start production server
npm run lint # Run ESLint on codebaseThe app demonstrates different state management approaches:
- Server State - Fetched via server actions in
getTools.js - Client State - localStorage for likes persistence
- Optimistic State - Instant UI feedback with
useOptimistic - React State - Local component state for UI interactions
Edit lib/getTools.js:
const TOOLS = [
"JavaScript",
"React",
// Add your framework here
"MyFramework",
];Edit lib/icons-data.js and add a new object to the ICONS array:
{
id: "MyFramework",
icon: (
<svg>
{/* Your SVG here */}
</svg>
),
}- Global styles:
app/globals.css - Component styles: Inline with Tailwind classes
- Configuration:
tailwind.config.js
# Change port
npm run dev -- -p 3001# Clear Next.js cache
rm -rf .next
# Reinstall dependencies
rm -rf node_modules package-lock.json
npm install
# Build again
npm run buildThe app includes hydration safety checks. If you see hydration warnings:
- Check for date/time differences between server and client
- Verify
useEffectis used for client-only code - Ensure Suspense boundaries wrap dynamic content
Contributions are welcome! Please:
- 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
This project is licensed under the MIT License - see the LICENSE file for details.
For issues, questions, or suggestions:
- Check the GitHub Issues
- Review the Next.js Documentation
- Visit the React Documentation
- Add search and filtering functionality
- Implement sorting options (A-Z, popularity)
- Add backend API for persistent storage
- Database integration for likes
- Analytics tracking
- Dark/Light mode toggle
- Multi-language support
- PWA support
Made with β€οΈ using Next.js 15