Why are the Kroki-generated images in my Backstage TechDocs site broken? - mkdocs

I am generating a TechDocs site for my Backstage server using the recommended approach with the techdocs-cli generate and publish commands in a CI/CD pipeline. I am also using the kroki plugin. My mkdocs.yaml includes the following:
plugins:
- techdocs-core
- kroki:
DownloadImages: true
FencePrefix: ''
HttpMethod: POST
ServerURL: http://localhost:8000
The generated .html files include links to generated images that look like <img alt="Kroki" src="/images/kroki_generated/<file>-<hash>.svg" />. Those svg files are present in the images/kroki_generated directory and the whole directory structure is published to an Azure storage account.
My Backstage server is deployed with the app-backend plugin and I'm accessing it at the root of a domain like https://techhub.example.com/
When I go to the page in the docs site in backstage, for example https://techhub.example.com/docs/default/component/<component name>/<document>/, the images are broken. The browser devtools are showing requests to https://techhub.example.com/images/kroki_generated/<file>-<hash>.svg which returns the Backstage app's home page HTML rather than retrieving the actual svg through the techdocs backend API.
How can I get the combination of TechDocs, MkDocs and the kroki plugin to work together properly?

This was caused by a defect in the MkDocs Kroki plugin which was fixed with https://github.com/AVATEAM-IT-SYSTEMHAUS/mkdocs-kroki-plugin/pull/20

Related

HTML file structure's affect on website URL

I currently have a simple website, hosted on github pages with a file structured in hierarchical directories as shown below:
/foobar.com
/css
/js
/images
/html
/news
/news_content
fizz.html
buzz.html
news.html
about.html
contact.html
index.html
However, when I am on the buzz webpage for example, this has resulted in the URL to become:
https://foobar.com/html/news/news_content/buzz.html
Is there a way to change this URL so that it doesn't show all the folder directories and instead, just the file itself i.e. https://foobar.com/buzz.html as I don't want to separate all the individual HTML files into separate folders?
Yes, you can change the URL to be more user-friendly by using server-side URL rewriting or client-side JavaScript.
For server-side URL rewriting, you'll need to use a web server such as Apache or Nginx and configure it to rewrite the URLs. You can find more information on how to do this for Apache or Nginx by searching for "URL rewriting" on their websites or forums.
For client-side URL rewriting, you can use JavaScript to manipulate the URL shown in the browser's address bar. However, this method may not be ideal for search engines or users who have JavaScript disabled.
If you are using GitHub Pages to host your website, you might be able to achieve URL rewriting by using Jekyll. Jekyll is a static site generator that supports URL rewriting and can be used in combination with GitHub Pages to host your website. You can find more information on how to do this by searching for "Jekyll URL rewriting."
How a URL is resolved to a resource depends on the HTTP server and/or the server side programming language you are using.
Github Pages provides no features that allow anything other than a direct reflection of the directory layout in the URL.
The closest you could come would be to write a program that transformed the input (the file structure you want to work with) into the file structure that Github Pages will express as the URLs you desire (and then run it as a build step that takes the pages out of your working branch and into your gh-pages branch; possibly you could use actions to do this).

Why are my local html links going to parent folder instead of the .html?

EDIT: Waylan's answer did the trick! Thanks!
I'm trying to zip .html files of docs to send to a customer. The goal is to have the same experience as navigating an actual website.
When opening the .html files, any link that is clicked goes to the parent folder, rather than the specific .html. For example, if I click on the link for the configuration page, it takes me to this parent folder (shown in the picture) with an index.html to the actual page. This is only happening in my local instance when I'm going through the .html files -- not when I'm navigating the built .md (using MkDocs).
macOS Catalina, 10.15.3
MkDocs
Markdown
You probably want to set use_directory_urls: false in your mkdocs.yml config file.
The behavior you are seeing is based on a feature of web servers. If you request a directory (for example /foo/) then the server will return the index page within that directory (/foo/index.html). MkDocs makes use of this feature to provide "pretty URLs" (URLs which do not have file extensions).
Therefore, when building the site, MkDocs will convert every page to an index file within a directory and will also rewrite all of the internal links to point to those locations. So long as the pages are hosted on a server which is configured to serve index pages (most are by default), this is not an issue.
However, if you are browsing the files locally without a web server or happen to be using a server which is not configured to handle index files, then you will see the behavior you are getting. You have two options:
Use a properly configured server.
Turn off the feature with MkDoc' use_directory_urls configuration setting.
To do the latter, add the following to your mkdocs.yml config file:
use_directory_urls: false
Then rebuild the site with mkdocs build. Now your pages will not all be index files.
Note that while this allows you to browse the files without a server (using file:///), due to browser security policies, search will no longer work within a MkDocs site. Therefore, it is recommended that you always use a server. That also explains why the default configuration expects a server.

Vue-Nuxt: Why can't I see the generated HTMLs correctly?

So when I type npm run generate Nuxt generates my project into the dist folder. In that folder I can find a folder called _nuxt where I have .js files and the index.html file but when I open it in a browser it doesn't show anything.
So, my question is: Aren't those static files?
When you work with the CDN served vue.js you have the html file and you click and everything is showed on the browser because those .html files are static, they don't need an internal localhost server. Why npm run generate doesn't do the same? Or how can I see those generated files?
As #aljazerzen explained, Vue,js doesn't do SSR out of the box, one of the aims of Nuxt.js is to provide SSR for you, as a benefit you can also generate a static version of your website. If I get what you want correctly, what you want to do is that when you open your index.html (the one that Nuxt.js generates for you) you can see your functional webpage. When you're accessing your website as a file:/// url, your browser (at least I've seen it happen with Chrome) doesn't load your .js files.
I don't have any Nuxt generated websites at hand so I can't tell you exactly why this happen. But this is my guess: when Nuxt generate those files it gives them a src that can't be accessed as file:///, maybe something as /your_js.js, that when it tries to load it, thinks it's the / of the root folder instead of relative to your website's root (/).
The solution to this problem is to serve your assets using any web server. According to Nuxt.js's documentation:
nuxt generate :Build the application and generate every route as a HTML file (used for static hosting).
You could do a quick test and use a simple web server by typing:
python -m http.server
In the folder that contains your generated assets.
Hope this helps!
Nuxt uses server side rendering.
You can read more here.
To generate static HTML files, run:
nuxt generate
Explanation: Vanilla Vue.js application is rendered only when the page loads and JavaScript can start running. This means that some clients that do not have JavaScript enabled (web crawlers) won't see the page. Also for a brief second before Vue.js can render the page, there is blank screen, when plain HTML files could already be visible.
Now, server-side rendering (SSR) is a technique for rendering a single page app (SPA) on the server and then sending a fully rendered page to the client. The client’s JavaScript bundle can then take over and the SPA can operate as normal.
This can also help with SEO and with providing meta data to social media channels.
But on the downside (as you mentioned), such application cannot be hosted at a CDN, since you have to have a Node.js process running to render the page.
In my opinion, SSR is redundant with SPAs if what you are building is actually an application and not a website. A website should mostly display information and should not be interactive. It should leverage web-based mechanisms such as links, cookies and plain HTML with CSS. In the contrast, web application (eg. Vue.js application) should be more like a mobile application: it is larger to download, but performs better and offers much more interactive experience. Such application does not need server-side rendering, since we can wait for it to load a bit more and because it shouldn't be indexed by search engines (it is not a website).

Embed create-react-app in dev mode on another site

I'm developing a Wordpress "widget" that is going to be a little react app. I've chosen create-react-app for this purpose.
Now I can see how to run the development server standalone easily enough, but I'd like to develop it while it sits inside the Wordpress website. I've created a trivial "Custom HTML" widget:
<div id="root"></div>
<script type="text/javascript" src="http://localhost:8080/static/js/bundle.js"></script>
This does not seem to work however...
Note I came up with /static/js/bundle.js by looking at the requests in the network tab when loading http://localhost:8080 directly, which is the prescribed way to access the dev version of the app.
So how do I access the development version of the app (with all the live reloading goodness) while embedded on my local version of the Wordpress site?
I had this same problem today in a PHP app I am developing. It is very frustrating to embed a create-react-app in development mode, and I had to consult a lot of different resources to learn how to do so. Here is a summary of my findings.
Using an iframe
Using an iframe to embed the create-react-app, as #quickshiftin suggests, is not a bad idea, but if you wish to pass configuration to the embedded SPA by calling methods or setting global variables in Javascript, it will not work* -- as the MDN documentation says (https://developer.mozilla.org/en-US/docs/Web/HTML/Element/iframe#scripting), iframes are subject to the same-origin policy.
* (Note: I found out after writing most of this answer that there is indeed a way to bypass the same-origin policy. It's called Window.postMessage(), and it's also mentioned in the section of the MDN documentation that I linked above. You may want to consider using that. But if you would like to avoid using an iframe for whatever reason, read on :)
Create-React-App file structure; embedding in production mode
The first thing you must know is that embedding bundle.js is not enough -- create-react-app builds multiple JS files that need to be embedded using <script> tags in the correct order. This blog post by Jeremiah Tabb describes the file structure of the bundled code and suggests a way to embed the create-react-app in production: https://betterprogramming.pub/how-to-embed-a-react-application-on-any-website-1bee1d15617f
The filenames of the bundled code contain hashes which change at every build. The hashing can't be disabled, it's a WONTFIX in create-react-app (https://github.com/facebook/create-react-app/issues/821). So, to get the bundled js filenames for a production build, in PHP, you can just traverse the build/static/js directory and output one <script> tag per .js file you find. (It may be wasteful to always request all chunks, but I haven't yet taken the time to look into the right way to do it.)
Development mode looks for chunks under the wrong path
But in development mode, which is your actual question, it is handled a bit differently. The index.html served by the dev server only loads three scripts initially: bundle.js, vendors~main.chunk.js and main.chunk.js. The other chunks are loaded dynamically. You can try embedding those three scripts on your Wordpress page, but you will find that at runtime, the 'bootstrap' code generated by Webpack looks for the chunks at the wrong URL, using e.g. localhost instead of localhost:3000, resulting in a chunk loading error.
PUBLIC_URL and "homepage" don't work in development mode
According to the Create-React-App documentation and various other answers on this site, you're supposed to be able to use the environment variable PUBLIC_URL or the key "homepage" in package.json to override the hostname and port where the JS code is served so that the chunks will load, but these settings don't do anything in development mode. This is an open issue in create-react-app: https://github.com/facebook/create-react-app/issues/9001
Workaround using npx patch-package
You might think you are in trouble and will have to eject your project and modify the webpack configuration yourself to get this working. But fortunately, there is a workaround described here in a comment by SergeyVolynkin which solves the problem without ejecting, using npx patch-package to patch react-dev-utils:
https://github.com/facebook/create-react-app/issues/9001#issuecomment-838370686
What SergeyVolynkin does not mention is that, after creating the patch and checking it into VCS, you should set up patch-package in your package.json so that the patches will be applied by npm / yarn when you run yarn / npm install. See the documentation for patch-package here: https://github.com/ds300/patch-package#set-up
Summary
After applying SergeyVolynkin's patch, I was able to get the development build embedded in my PHP app. I used the following scripts in my package.json:
"scripts": {
"start": "PORT=1234 PUBLIC_URL=http://localhost:1234 WDS_SOCKET_PORT=1234 react-scripts start",
"postinstall": "patch-package"
}
And I used the following lines in the HTML served by my PHP app:
<script src="http://localhost:1234/static/js/bundle.js"></script>
<script src="http://localhost:1234/static/js/vendors~main.chunk.js"></script>
<script src="http://localhost:1234/static/js/main.chunk.js"></script>
By doing this, I could embed an app created using create-react-app in dev mode in my PHP app.

How do I get a largely HTML site generated from a rails app?

I would like to create a Rails 4 app, where some data is entered into the db via a form and when it is published, any changes on the site are compiled and the entire consumer facing site is just a bunch of flat HTML files.
That way, on each request there isn't a db request done and just a simple HTML file is sent.
This is similar to the way Octopress operates, where you write a blog post locally and when you do a deploy it basically compiles the entire site into a large set of connected HTML files that are then pushed to your host(gh-pages for instance).
Is there a way to use extensive caching or something similar to get the same effect in Rails 4 or should I go about it another way in Rails or should I just try to customize Octopress for my needs?
Have a look at page caching, it has been moved from Rails to a separate gem
https://github.com/rails/actionpack-page_caching
It saves the generated HTML files to a specified directory which you should be able to deploy separately from the rest of the application.