A simple, lightweight React component library for embedding content via Embedly's OEmbed API in Next.js applications.
- ✅ Simple React component for rendering embeds
- ✅ Full TypeScript support with comprehensive types
- ✅ Server-side API utility for secure key handling
- ✅ Supports all OEmbed types (video, photo, rich, link)
- ✅ Customizable loading and error states
- ✅ Works with both App Router and Pages Router
- ✅ Zero dependencies (except React and Next.js peer deps)
npm install @embedly/nextjsSign up at embed.ly and get your API key.
Create a .env.local file in your Next.js project:
EMBEDLY_API_KEY=your_api_key_hereThe API key must be kept server-side for security. Create an API route to proxy requests to Embedly.
Create app/api/embedly/route.ts:
import{NextRequest,NextResponse}from'next/server';import{fetchEmbedlyData}from'@embedly/nextjs';exportasyncfunctionGET(request: NextRequest){constapiKey=process.env.EMBEDLY_API_KEY;if(!apiKey){returnNextResponse.json({error: 'Embedly API key not configured'},{status: 500});}constsearchParams=request.nextUrl.searchParams;consturl=searchParams.get('url');if(!url){returnNextResponse.json({error: 'URL parameter is required'},{status: 400});}try{constembedData=awaitfetchEmbedlyData(apiKey,{
url,maxWidth: searchParams.get('maxWidth') ? parseInt(searchParams.get('maxWidth')!,10) : undefined,maxHeight: searchParams.get('maxHeight')
? parseInt(searchParams.get('maxHeight')!,10)
: undefined,});returnNextResponse.json(embedData);}catch(error){returnNextResponse.json({error: errorinstanceofError ? error.message : 'Failed to fetch embed data'},{status: 500});}}Create pages/api/embedly.ts:
importtype{NextApiRequest,NextApiResponse}from'next';import{fetchEmbedlyData,OEmbedResponse}from'@embedly/nextjs';exportdefaultasyncfunctionhandler(req: NextApiRequest,res: NextApiResponse<OEmbedResponse|{error: string}>){if(req.method!=='GET'){returnres.status(405).json({error: 'Method not allowed'});}constapiKey=process.env.EMBEDLY_API_KEY;if(!apiKey){returnres.status(500).json({error: 'Embedly API key not configured'});}const{ url, maxWidth, maxHeight }=req.query;if(!url||typeofurl!=='string'){returnres.status(400).json({error: 'URL parameter is required'});}try{constembedData=awaitfetchEmbedlyData(apiKey,{
url,maxWidth: maxWidth ? parseInt(maxWidthasstring,10) : undefined,maxHeight: maxHeight ? parseInt(maxHeightasstring,10) : undefined,});returnres.status(200).json(embedData);}catch(error){returnres.status(500).json({error: errorinstanceofError ? error.message : 'Failed to fetch embed data',});}}import{EmbedlyEmbed}from'@embedly/nextjs';exportdefaultfunctionMyPage(){return(<div><h1>Check out this video!</h1><EmbedlyEmbedurl="https://www.youtube.com/watch?v=dQw4w9WgXcQ"/></div>);}The main React component for rendering embeds.
| Prop | Type | Default | Description |
|---|---|---|---|
url | string | Required | The URL to embed |
apiEndpoint | string | /api/embedly | Your Next.js API route endpoint |
maxWidth | number | undefined | Maximum width for the embed |
maxHeight | number | undefined | Maximum height for the embed |
loading | ReactNode | Loading message | Custom loading component |
error | (error: Error) => ReactNode | Error message | Custom error renderer |
onLoad | (data: OEmbedResponse) => void | undefined | Callback when data loads |
onError | (error: Error) => void | undefined | Callback when error occurs |
className | string | undefined | Additional CSS class |
style | CSSProperties | undefined | Additional inline styles |
Server-side utility function for fetching OEmbed data.
asyncfunctionfetchEmbedlyData(apiKey: string,options: EmbedlyFetchOptions): Promise<OEmbedResponse>apiKey: Your Embedly API key (keep this secret!)options.url: The URL to fetch embed data foroptions.maxWidth: (optional) Maximum width constraintoptions.maxHeight: (optional) Maximum height constraint
<EmbedlyEmbedurl="https://www.youtube.com/watch?v=dQw4w9WgXcQ"/><EmbedlyEmbedurl="https://vimeo.com/76979871"loading={<Spinner/>}error={(err)=><ErrorMessagemessage={err.message}/>}/><EmbedlyEmbedurl="https://www.flickr.com/photos/example/123456789"maxWidth={600}maxHeight={400}/><EmbedlyEmbedurl="https://twitter.com/username/status/123456789"onLoad={(data)=>{console.log('Embed type:',data.type);console.log('Provider:',data.provider_name);}}onError={(err)=>{console.error('Failed to load embed:',err);}}/><EmbedlyEmbedurl="https://soundcloud.com/artist/track"className="my-embed"style={{marginTop: '2rem',padding: '1rem',border: '1px solid #ccc',}}/>Embedly supports over 1000 content providers including:
- YouTube, Vimeo, Dailymotion
- Twitter, Instagram, Facebook
- SoundCloud, Spotify
- Flickr, Imgur
- And many more!
See the full provider list.
This library is written in TypeScript and includes comprehensive type definitions:
importtype{OEmbedResponse,OEmbedVideoResponse,OEmbedPhotoResponse,OEmbedRichResponse,OEmbedLinkResponse,EmbedlyFetchOptions,}from'@embedly/nextjs';Important: Never expose your Embedly API key to the client-side. Always use it server-side in your API routes.
The library is designed with security in mind:
- API key is only used server-side
- Client component communicates through your Next.js API route
- No direct client-to-Embedly API calls
MIT
Contributions are welcome! Please feel free to submit a Pull Request.
- 🐛 Bug Reports:Open an issue on GitHub
- 💬 Discussions:Start a discussion
- 🔧 Pull Requests: Contributions are welcome! See CONTRIBUTING.md
- 📧 Email:support@embed.ly
- 📚 API Documentation:docs.embed.ly/reference/embedly-api
- 🔑 Get API Key:embed.ly/signup