- Updated REAMDE.md to reflect current file & folder structure
- Fixed Navbar not working
- Added middleware exceptions for api and public/ (to not auto link to i18n version)
- Fixed blog [slug] and [tag] pages not rendering properly (prerender = true)
This commit is contained in:
Cyril Šebek 2024-06-21 09:20:24 +02:00
parent 5d7cdeb999
commit a1b94ae545
Signed by: blboun3
SSH Key Fingerprint: SHA256:ESaOKDAPaR/9j4DJ3sU4VdxTcL7qWUxpAyPSK2LLKbY
6 changed files with 139 additions and 35 deletions

View File

@ -1,7 +1,7 @@
# Personal themeable i18n compatible website in astro # My personal website
Welcome to my personal [website](https://cyrilsebek.cz)
Code for my personal website written in astro with react.js elements.
i18n compatible (even blog), easily CSS stylable (one .css file for everything)
## 🚀 Project Structure ## 🚀 Project Structure
@ -10,32 +10,68 @@ The file & folder structure is as follows:
```text ```text
/ /
├── public/ ├── public/
│ └── favicon.svg │ ├── favicon.svg
│ └── music/
│ ├── first/
│ │ ├── my.flac
│ │ ├── my.mp3
│ │ └── my.pdf
│ ├── second/
│ └── .../
├── src/ ├── src/
│ ├── components/ │ ├── components/
│ │ └── Card.astro │ ├── content/
│ │ ├── blog/
│ │ │ ├── blog-post-1/
│ │ │ │ ├── cs.md
│ │ │ │ ├── de.md
│ │ │ │ ├── en.md
│ │ │ │ └── fr.md
│ │ │ ├── blog-post-2/
│ │ │ └── .../
│ │ ├── music/
│ │ │ ├── first.md
│ │ │ ├── second.md
│ │ │ └── ...
│ │ └── config.js
│ ├── i18n/
│ │ ├── cs.js
│ │ ├── de.js
│ │ ├── en.js
│ │ ├── fr.js
│ │ ├── dictionary.js
│ │ └── utils.ts
│ ├── icons/
│ ├── layouts/ │ ├── layouts/
│ │ └── Layout.astro │ ├── lib/
│ └── pages/ │ │ ├── icons.js
│ └── index.astro │ │ └── utils.js
│ ├── pages/
│ ├── style/
│ │ └── index.css
│ ├── env.d.ts
│ └── middleware.js
└── package.json └── package.json
``` ```
Astro looks for `.astro` or `.md` files in the `src/pages/` directory. Each page is exposed as a route based on its file name. Astro looks for `.astro` or `.md` files in the `src/pages/` directory. **Each page is exposed as a route based on its file name.**
There's nothing special about `src/components/`, but that's where we like to put any Astro/React/Vue/Svelte/Preact components. There's nothing special about `src/components/`, but that's where we like to put any Astro/React/Vue/Svelte/Preact components.
Any static assets, like images, can be placed in the `public/` directory. Any static assets, like images, can be placed in the `public/` directory.
Content is placed in the `src/content/` directory into the appropriate subfolder.
## 🧞 Commands ## 🧞 Commands
All commands are run from the root of the project, from a terminal: All commands are run from the root of the project, from a terminal:
| Command | Action | | Command | Action |
| :------------------------ | :----------------------------------------------- | | :----------------------------- | :----------------------------------------------- |
| `npm install` | Installs dependencies | | `npm install` | Installs dependencies |
| `npm run dev` | Starts local dev server at `localhost:4321` | | `npm run dev` | Starts local dev server at `localhost:4321` |
| `npm run build` | Build your production site to `./dist/` | | `npm run build` | Build your production site to `./dist/` |
| `npm run preview` | Preview your build locally, before deploying | | `npm run preview` | Preview your build locally, before deploying |
| `npm run astro ...` | Run CLI commands like `astro add`, `astro check` | | `npm run astro ...` | Run CLI commands like `astro add`, `astro check` |
| `npm run astro -- --help` | Get help using the Astro CLI | | `npm run astro -- --help` | Get help using the Astro CLI |
| `node ./dist/server/entry.mjs` | Runs app after building |

View File

@ -1,5 +1,4 @@
--- ---
import { getRelativeLocaleUrl } from "astro:i18n";
import { ThemeSelector } from "./ThemeSelector" import { ThemeSelector } from "./ThemeSelector"
import NavbarSkeleton from "./NavbarSkeleton.astro"; import NavbarSkeleton from "./NavbarSkeleton.astro";
import { LangSwitcher } from "./LangSwitcher"; import { LangSwitcher } from "./LangSwitcher";
@ -7,8 +6,7 @@ import { NavButton } from "./NavButton";
function selected(path) { function selected(path) {
var currentURL = Astro.url.pathname var currentURL = Astro.url.pathname
.replace(Astro.currentLocale + "/", "") .replace(Astro.currentLocale + "/", "") || "/"
.slice(0, -1) || "/";
if( path == "/blog" && currentURL.startsWith("/blog") ){ if( path == "/blog" && currentURL.startsWith("/blog") ){
return (true); return (true);
} }

View File

@ -9,20 +9,80 @@ image:
language: "en" language: "en"
tags: ["test"] tags: ["test"]
--- ---
## Story about Old days # My personal website
In the olden days, Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Vitae ultricies leo integer malesuada nunc vel risus commodo viverra. Adipiscing enim eu turpis egestas pretium. Euismod elementum nisi quis eleifend quam adipiscing. In hac habitasse platea dictumst vestibulum. Sagittis purus sit amet volutpat. Netus et malesuada fames ac turpis egestas. Eget magna fermentum iaculis eu non diam phasellus vestibulum lorem. Varius sit amet mattis vulputate enim. Habitasse platea dictumst quisque sagittis. Integer quis auctor elit sed vulputate mi. Dictumst quisque sagittis purus sit amet.
## Conclusion Welcome to my personal [website](https://cyrilsebek.cz)
Morbi tristique senectus et netus. Id semper risus in hendrerit gravida rutrum quisque non tellus. Habitasse platea dictumst quisque sagittis purus sit amet. Tellus molestie nunc non blandit massa. Cursus vitae congue mauris rhoncus. Accumsan tortor posuere ac ut. Fringilla urna porttitor rhoncus dolor. Elit ullamcorper dignissim cras tincidunt lobortis. In cursus turpis massa tincidunt dui ut ornare lectus. Integer feugiat scelerisque varius morbi enim nunc. Bibendum neque egestas congue quisque egestas diam. Cras ornare arcu dui vivamus arcu felis bibendum. Dignissim suspendisse in est ante in nibh mauris. Sed tempus urna et pharetra pharetra massa massa ultricies mi.
## Story about Old days
In the olden days, Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Vitae ultricies leo integer malesuada nunc vel risus commodo viverra. Adipiscing enim eu turpis egestas pretium. Euismod elementum nisi quis eleifend quam adipiscing. In hac habitasse platea dictumst vestibulum. Sagittis purus sit amet volutpat. Netus et malesuada fames ac turpis egestas. Eget magna fermentum iaculis eu non diam phasellus vestibulum lorem. Varius sit amet mattis vulputate enim. Habitasse platea dictumst quisque sagittis. Integer quis auctor elit sed vulputate mi. Dictumst quisque sagittis purus sit amet.
## Conclusion ## 🚀 Project Structure
Morbi tristique senectus et netus. Id semper risus in hendrerit gravida rutrum quisque non tellus. Habitasse platea dictumst quisque sagittis purus sit amet. Tellus molestie nunc non blandit massa. Cursus vitae congue mauris rhoncus. Accumsan tortor posuere ac ut. Fringilla urna porttitor rhoncus dolor. Elit ullamcorper dignissim cras tincidunt lobortis. In cursus turpis massa tincidunt dui ut ornare lectus. Integer feugiat scelerisque varius morbi enim nunc. Bibendum neque egestas congue quisque egestas diam. Cras ornare arcu dui vivamus arcu felis bibendum. Dignissim suspendisse in est ante in nibh mauris. Sed tempus urna et pharetra pharetra massa massa ultricies mi.
## Story about Old days The file & folder structure is as follows:
In the olden days, Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Vitae ultricies leo integer malesuada nunc vel risus commodo viverra. Adipiscing enim eu turpis egestas pretium. Euismod elementum nisi quis eleifend quam adipiscing. In hac habitasse platea dictumst vestibulum. Sagittis purus sit amet volutpat. Netus et malesuada fames ac turpis egestas. Eget magna fermentum iaculis eu non diam phasellus vestibulum lorem. Varius sit amet mattis vulputate enim. Habitasse platea dictumst quisque sagittis. Integer quis auctor elit sed vulputate mi. Dictumst quisque sagittis purus sit amet.
## Conclusion ```text
Morbi tristique senectus et netus. Id semper risus in hendrerit gravida rutrum quisque non tellus. Habitasse platea dictumst quisque sagittis purus sit amet. Tellus molestie nunc non blandit massa. Cursus vitae congue mauris rhoncus. Accumsan tortor posuere ac ut. Fringilla urna porttitor rhoncus dolor. Elit ullamcorper dignissim cras tincidunt lobortis. In cursus turpis massa tincidunt dui ut ornare lectus. Integer feugiat scelerisque varius morbi enim nunc. Bibendum neque egestas congue quisque egestas diam. Cras ornare arcu dui vivamus arcu felis bibendum. Dignissim suspendisse in est ante in nibh mauris. Sed tempus urna et pharetra pharetra massa massa ultricies mi. /
├── public/
│ ├── favicon.svg
│ └── music/
│ ├── first/
│ │ ├── my.flac
│ │ ├── my.mp3
│ │ └── my.pdf
│ ├── second/
│ └── .../
├── src/
│ ├── components/
│ ├── content/
│ │ ├── blog/
│ │ │ ├── blog-post-1/
│ │ │ │ ├── cs.md
│ │ │ │ ├── de.md
│ │ │ │ ├── en.md
│ │ │ │ └── fr.md
│ │ │ ├── blog-post-2/
│ │ │ └── .../
│ │ ├── music/
│ │ │ ├── first.md
│ │ │ ├── second.md
│ │ │ └── ...
│ │ └── config.js
│ ├── i18n/
│ │ ├── cs.js
│ │ ├── de.js
│ │ ├── en.js
│ │ ├── fr.js
│ │ ├── dictionary.js
│ │ └── utils.ts
│ ├── icons/
│ ├── layouts/
│ ├── lib/
│ │ ├── icons.js
│ │ └── utils.js
│ ├── pages/
│ ├── style/
│ │ └── index.css
│ ├── env.d.ts
│ └── middleware.js
└── package.json
```
Astro looks for `.astro` or `.md` files in the `src/pages/` directory. **Each page is exposed as a route based on its file name.**
There's nothing special about `src/components/`, but that's where we like to put any Astro/React/Vue/Svelte/Preact components.
Any static assets, like images, can be placed in the `public/` directory.
Content is placed in the `src/content/` directory into the appropriate subfolder.
## 🧞 Commands
All commands are run from the root of the project, from a terminal:
| Command | Action |
| :----------------------------- | :----------------------------------------------- |
| `npm install` | Installs dependencies |
| `npm run dev` | Starts local dev server at `localhost:4321` |
| `npm run build` | Build your production site to `./dist/` |
| `npm run preview` | Preview your build locally, before deploying |
| `npm run astro ...` | Run CLI commands like `astro add`, `astro check` |
| `npm run astro -- --help` | Get help using the Astro CLI |
| `node ./dist/server/entry.mjs` | Runs app after building |

View File

@ -6,11 +6,17 @@ const langs = ["en", "de", "cs", "fr"]
export const userMiddleware = defineMiddleware(async (ctx, next) => { export const userMiddleware = defineMiddleware(async (ctx, next) => {
// this response might come from Astro's i18n middleware, and it might return a 404 // this response might come from Astro's i18n middleware, and it might return a 404
const response = await next(); const response = await next();
// the /about page is an exception and we want to render it
if (ctx.url.pathname == "/") { const exceptions = ["/api", "/public"]
return Response.redirect(`${ctx.url.protocol}${ctx.url.host}/en/`);
// If path is in exceptions (i.e. api or public) return default middleware to handle it
if (exceptions.includes(ctx.url.pathname) ) {
return response
// If no lang is set => set to english (some pages are language-les exceptions)
} else if ( !langs.some(item => ctx.url.href.includes(item)) ) { } else if ( !langs.some(item => ctx.url.href.includes(item)) ) {
return Response.redirect(`${ctx.url.protocol}${ctx.url.host}/en${ctx.url.pathname}`); return Response.redirect(`${ctx.url.protocol}${ctx.url.host}/en${ctx.url.pathname}`);
} else { } else {
return response; return response;
} }

View File

@ -1,6 +1,7 @@
--- ---
export const prerender = true export const prerender = true
import { Separator } from "../../../components/ui/separator";
import { getBlogPosts } from "../../../content/config"; import { getBlogPosts } from "../../../content/config";
import BlogPost from "../../../layouts/BlogPost.astro"; import BlogPost from "../../../layouts/BlogPost.astro";
@ -39,6 +40,7 @@ const { Content } = await page.render();
<a href={`${Astro.url.origin}/${Astro.currentLocale}/blog/tags/${tag}`}>#{tag}</a> <a href={`${Astro.url.origin}/${Astro.currentLocale}/blog/tags/${tag}`}>#{tag}</a>
)} )}
</div> </div>
<Separator className="my-4"/>
</div> </div>
<Content /> <Content />
</article> </article>

View File

@ -1,4 +1,6 @@
--- ---
export const prerender = true
import MainLayout from "../../../../layouts/MainLayout.astro"; import MainLayout from "../../../../layouts/MainLayout.astro";
import SinglePageBlogMode from "../../../../layouts/SinglePageBlogMode.astro"; import SinglePageBlogMode from "../../../../layouts/SinglePageBlogMode.astro";
import { LANGUAGES, getLangFromUrl, useTranslations } from "../../../../i18n/utils"; import { LANGUAGES, getLangFromUrl, useTranslations } from "../../../../i18n/utils";