How to embed youtube videos in mdx files using Next.js with Nextra library? - javascript

I am using this Portfolio Starter Kit for my travel blog. The only feature I am missing there is a way to embed youtube videos into the blog post, so that they would play on-the-spot, without opening the video on youtube.com on a new page.
I used ChatGPT-s help, but since I am new to Next.js and Nextra I am unable to spot ChatGPT-s mistakes and debug them. This was it's recommendation:
Install the react-youtube package in your project:
yarn add react-youtube
Create a custom MDX component to render YouTube videos:
Create a new file in your project directory called YouTube.js. In this file, define a new component that uses the YouTube component from the react-youtube library to render YouTube videos. Here is an example of what this file could look like:
import YouTube from 'react-youtube';
const YouTubeComponent = ({ videoId }) => {
const opts = {
height: '360',
width: '640',
playerVars: {
// https://developers.google.com/youtube/player_parameters
autoplay: 0,
},
};
return <YouTube videoId={videoId} opts={opts} />;
};
export default YouTubeComponent;```
Register the custom MDX component in your Next.js configuration:
In your Next.js configuration file (usually next.config.js), you can register the YouTubeComponent as a custom MDX component by adding the following code:
const withMDX = require('#next/mdx')({
extension: /\.mdx?$/,
options: {
remarkPlugins: [],
rehypePlugins: [],
// Register custom components here
// Here, we're registering a component called 'youtube' that uses our custom YouTubeComponent
components: {
youtube: './components/YouTube',
},
},
});
module.exports = withMDX();
Use the custom component in your Markdown content:
In your Markdown content, you can now use the 'youtube' tag to embed YouTube videos. Here is an example of what this could look like:
Here is a YouTube video:
<youtube videoId="dQw4w9WgXcQ" />
After adding all this and runnin yarn run build I get this error:
Failed to compile.
./pages/ajaveeb/2023-02-18-youtube-embedding.mdx
TypeError [ERR_INVALID_ARG_TYPE]: The "from" argument must be of type string. Received undefined
at new NodeError (node:internal/errors:400:5)
at validateString (node:internal/validators:163:11)
at Object.relative (node:path:1191:5)
at loader (file:///Users/kristjan.roosild/repos/what-does-this-button-do/node_modules/nextra/dist/loader.mjs:85:42)
Here is the PR of the changes https://github.com/kristjanr/what-does-this-button-do/pull/1/files

Related

Client-only Nuxt 3 Vue plugin

I am new to Nuxt and Vue, so go easy on me. I am trying to create a video player component in my Nuxt 3 app using vue3-video-player, which doesn't seem to support SSR based on the following error I get when I import it in my video component:
ReferenceError: navigator is not defined
This error persists even if the component is wrapped with <ClientOnly>. So, based on what I saw in the Nuxt 3 Documentation I thought I would create a client-only plugin located at plugins/vue3-video-player.client.js with the following contents:
import Vue3VideoPlayer from '#cloudgeek/vue3-video-player'
export default defineNuxtPlugin((nuxtApp) => {
nuxtApp.vueApp.use(Vue3VideoPlayer)
})
But when I try to use it in my component as <vue3-video-player>, I get the following error:
[Vue warn]: Failed to resolve component: vue3-video-player
So I guess my question is how do I create a client-only Vue component using Nuxt 3 plugins? Or is there an entirely different approach that would work better?
Solution for nuxt 3:
Nuxt will automatically read the files in your plugins directory and load them. You can use .server or .client suffix in the file name to load a plugin only on the server or client side.
For example:
plugins/apexcharts.client.ts
Everything is so simple! And that is why we love nuxt ❤️
Solution for nuxt 2 (to show the difference):
nuxt.config.ts
plugins: [
{src: '~/plugins/apexcharts', mode: 'client'}
],
This is only for nuxt 2 because All plugins in your nuxt 3 plugins/ directory are auto-registered, so you should not add them to your nuxt.config separately.
you could try to provide a helper function. As mentioned in the docs.
import Vue3VideoPlayer from '#cloudgeek/vue3-video-player'
export default defineNuxtPlugin((nuxtApp) => {
return {
provide: {
Vue3VideoPlayer
}
}
})
To tag along with the given correct answer here,
If you're trying to install and use a third party NPM package, and running into "window is not defined" type errors, you can load the package as a plugin as follows (eg WAD)
npm install web-audio-daw
// plugins/wad.client.ts
import Wad from "web-audio-daw"
export default defineNuxtPlugin(nuxtApp => {
return {
provide: {
Wad,
}
}
})
// pages/whatever.vue
<script lang="ts" setup>
const { $Wad } = useNuxtApp();
// Can use $Wad normally from here on out
</script>

vue-router with parameter can't run deploy on netlify

Home.vue
<template>
<h3>Home</h3>
</template>
Test1.vue
<template>
<h3>TEst page {{symbol}}</h3>
</template>
<script>
export default {
data() {
return {
symbol: this.$route.params.id
}
},
}
</script>
export default new Router({
mode: 'history',
routes: [
{
path: '/test/:id',
component: Test1
},
{
path: '/home',
component: Home
},
]
})
I can't call through the website [netlifylink/test/1]. It's "Page Not Found
Looks like you've followed a broken link or entered a URL that doesn't exist on this site".
But can still access localhost:8080/test/1
i call localhost:8080/home and [netlifylink/home] is work. why?
help me please.Sorry for grammar.
It's also in the Vue documentation deployment section
https://cli.vuejs.org/guide/deployment.html#netlify
In order to receive direct hits using history mode on Vue Router, you need to create a file called _redirects under /public with the following content:
# Netlify settings for single-page application
/* /index.html 200
There are special deploy instructions for SPAs on Netlify. On this page: https://www.netlify.com/docs/redirects/ if you go to the History Pushstate and Single Page Apps section you will see this:
If you’re developing a single page app and want history pushstate to work so you get clean URLs, you’ll want to enable the following rewrite rule:
/* /index.html 200
This will effectively serve the index.html instead of giving a 404 no matter what URL the browser requests.
You need to add this to the _redirects file under the root of your built site.
create a file called netlify.toml in the root of your project and then paste this:
[[redirects]]
from = "/*"
to = "/index.html"
status = 200

GatsbyJS: How do I load a component synchronously at build time, but asynchronously at runtime?

I have a Gatsby site with a React component called ArticleBody that uses react-markdown to convert an article written in Markdown to a React tree.
As this is a bit of an expensive operation and a somewhat large component — and for SEO reasons — I'd like to pre-render ArticleBody at build time. However, I'd also like to load ArticleBody asynchronously in the client. Since the article body will already be included in the HTML, there's no rush to load and render the Markdown component in the client, so async should be fine.
How would I accomplish this? It's almost as if I want to have two different JS bundles — one bundle that loads ArticleBody synchronously, for the build, and one that loads it asynchronously, for the client. Is this possible in Gatsby?
Thanks!
Instead of React.lazy which is not supported, you can use loadable components. There is a Gatsby plugin to handle SSR correctly gatsby-plugin-loadable-components-ssr
Currently there is an issue with it since Gatsby 3.x, but there is a way to implement it yourself without the extra plugin. See the comment in the issue here. Also add the changes mentioned in the comment below of it.
I haven't tried this specific implementation yet, but it should work with the following steps:
npm install --save-dev #loadable/babel-plugin #loadable/server #loadable/webpack-plugin #loadable/component
gatsby-browser.js
import { loadableReady } from '#loadable/component'
import { hydrate } from 'react-dom'
export const replaceHydrateFunction = () => (element, container, callback) => {
loadableReady(() => {
hydrate(element, container, callback)
})
}
gatsby-node.js
exports.onCreateWebpackConfig = ({ actions, stage }) => {
if (
stage === "build-javascript" ||
stage === "develop" ||
stage === "develop-html"
) {
actions.setWebpackConfig({
plugins: [
new LoadablePlugin({
filename:
stage === "develop"
? `public/loadable-stats.json`
: "loadable-stats.json",
writeToDisk: true
})
]
});
}
};
gatsby-ssr.js
import { ChunkExtractor } from '#loadable/server'
import path from 'path'
const extractor = new ChunkExtractor({
// Read the stats file generated by webpack loadable plugin.
statsFile: path.resolve('./public/loadable-stats.json'),
entrypoints: [],
})
// extractor.collectChunks() will wrap the application in a ChunkExtractorManager
export const wrapRootElement = ({ element }) =>
extractor.collectChunks(element)
export const onRenderBody = ({ setHeadComponents, setPostBodyComponents }) => {
// Set link rel="preload" tags in the head to start the request asap. This will NOT parse the assets fetched
setHeadComponents(extractor.getLinkElements())
// Set script and style tags at the end of the document to parse the assets.
setPostBodyComponents([...extractor.getScriptElements(), ...extractor.getStyleElements()])
// Reset collected chunks after each page is rendered
extractor.chunks = []
}
If you have DEV_SSR enabled, you should not add stage === "develop-html". Otherwise, you are good.
Hope this summary of the issue's comments help to get you started.

Using a JS lib in typescript without definitely typed definition

I have an AspNet app using typescript with onsen ui.
When i called component from onsen, i used these ref
// <reference path="TypeScriptHelper/Onsen/OnsPageController.ts"/>
But i want to use a javascript lib called devexpress that has no .d.ts defintion
How can i called these controls from my typescript file ?
The script are inserted in the index.html
But when i call them in my typescript file like this :
DevExpress.Dashboard.ResourceManager.embedBundledResources();
// Creates a new Web Dashboard control with the specified ID and settings:
var dashboardControl = new DevExpress.Dashboard.DashboardControl(document.getElementById("container"), {
// Configures an URL where the Web Dashboard's server-side is hosted:
endpoint: "https://demos.devexpress.com/services/dashboard/api",
workingMode: "Viewer",
extensions: {
"dashboard-panel": (control) => new DevExpress.Dashboard.DashboardPanelExtension(control)
}
});
They are not recognized
Any idea why and how to fixe it ?
Thx in advance,

can't insert Facebook interstitial ads into react-native app

I want to use react-native-fbads in my react-native app (I've never used facebookAds) for inserting an Interstitial Ads.
This is what I've done in one of my app component (after react-native install react-native-fbads):
import { InterstitialAdManager } from 'react-native-fbads';
constructor(props) {
InterstitialAdManager.showAd("XXXXX_XXXXX") // this is line 16
.then(didClick => {console.log("clicked")})
.catch(error => {console.log("error")})
}
but I keep get this error: undefined is not an object (evaluating 'CTKInterstitialAdManager.showAd')
Have you try running react-native link react-native-fbads?
This will automatically link the library's native dependencies to your iOS/Android projects.

Categories