vojtamaur-web projectvojtamaur-web is a static website built with Astro. Content is managed as files in the repository and converted into static output during the build process. The project does not use a CMS or a database. The source of truth is the repository containing the source code, content, and static assets.
The project is divided into the following main content sections:
The architecture is based on the following components:
public/ for images, PDFs, demos, and other filesThis model makes it easier to version content, archive build outputs, and potentially migrate the project to another environment without relying on a database runtime.
The current project structure is divided into two main parts:
src/ – project source filespublic/ – static assets copied unchanged during the buildProvided structure:
public/
demos/
files/
images/
src/
components/
content/
content.config.ts
env.d.ts
layouts/
lib/
pages/
styles/
public/Contains static files that are simply copied into the output during the build:
public/images/ – article images, thumbnails, and other visual contentpublic/files/ – PDFs and other downloadable or embeddable filespublic/demos/ – standalone HTML/JS demos and legacy static pagessrc/content/Project content files. In the current configuration, the following are mainly used:
src/content/posts/ – articlessrc/content/videos/ – metadata for promotional videossrc/components/Reusable components for working with content and listings:
ImageFigure.astroMediaRow.astroEmbed.astroPostTileGrid.astroHeader.astrosrc/layouts/Layouts for individual page types:
BaseLayout.astroPostLayout.astroTravelLayout.astro and ExhibitionLayout.astrosrc/pages/Application routes. Includes the homepage, category pages, and dynamic article routing.
src/styles/Global and optionally other style files.
src/lib/Helper utilities and shared logic used across the project.
astro.config.mjsThe project uses two build modes. The configuration switches behavior according to the BUILD_TARGET variable. In the standard web build it uses trailingSlash: "always" and build.format: "directory". In the portable file-based build it uses trailingSlash: "never" and build.format: "file".
This produces two different output types:
package.jsonBasic project workflow:
npm run dev
npm run build:web
npm run preview
npm run build:usb
Meaning of the scripts:
npm run dev – starts the Astro development servernpm run build:web – creates the standard production buildnpm run preview – local preview of the buildnpm run build:usb – creates a portable file-based build and runs additional postprocessingcontent.config.tsDefines content collections and metadata schemas using Zod validation. The project uses at least the following collections:
postsvideosposts collectionArticles are stored as .mdx files and validated against the schema in content.config.ts.
Required metadata:
titleslugsectiondatethumbnailthumbnailAltOptional metadata:
excerptdraftSection-specific metadata:
section: "vystavy"dateFromdateTocityvenueexhibitionsection: "cestovani"yearmediavideos collectionUsed for the Propagační videa section. Contains metadata for external YouTube videos. Typically:
titleurlthumbnailthumbnailAltdraftPostLayout.astroPostLayout.astro wraps article content in the main layout and creates a shared wrapper for article pages.
[slug].astroThe [slug].astro file is the central route for content from the posts collection. It handles:
getCollectionslugrender(post)Different sections have different meta blocks:
In the Volná tvorba section, the date is displayed as month and year, for example:
duben 2026
Internally, the standard date field is still used for sorting.
Articles are sorted by date. This also applies in cases where the UI does not display the exact day, but only the month and year.
This project was created as a replacement for an older website with fragile infrastructure (outdated PHP, WordPress, unmaintained plugins, and dependence on third-party systems).
That legacy site displayed only the month and year for many articles in the Volná tvorba section (for example duben 2020). During migration, the exact original day was often no longer recoverable. In such cases, the date field was normalized to the first day of the given month (for example 2020-04-01) in order to preserve sorting behavior.
This means that for part of the legacy content, the stored day may be approximate and should be understood as a technical migration value rather than an exact historical publication date.
Articles added after April 2026 use the real day in the date field whenever that information is available.
A new article is added by creating a new .mdx file in:
src/content/posts/
The file must contain valid frontmatter according to the posts schema.
titleslugsectiondatethumbnailthumbnailAltexcerptdraftdateFromdateTocityvenueexhibitionyearmediaEach article uses:
thumbnail – path to the thumbnailthumbnailAlt – thumbnail alt textThumbnails are used in article listings, on the homepage, and in individual sections.
draftThe draft: true field excludes the article from the public listing and generated paths. It is used for content that is in progress or temporarily hidden.
Besides standard Markdown, article content can also use the following components:
ImageFigureMediaRowEmbedThese components must be explicitly imported in the MDX file.
EntryPoints.astroThe EntryPoints.astro component is used in the meta article to render the main archive entry points.
It reads the public/ARCHIVE.txt file, extracts the section between the markers === ENTRY POINTS START === and === ENTRY POINTS END ===, and displays it inside a <pre> block.
This ensures that the list of primary locations and snapshots is maintained in a single source of truth and does not need to be manually duplicated in the article content.
---
title: "Název článku"
slug: "nazev-clanku"
section: "volna-tvorba"
date: 2026-04-19
thumbnail: "/images/nazev-clanku-nahled.jpg"
thumbnailAlt: "Náhled článku"
excerpt: ""
draft: false
---
---
title: "Recamánova struktura"
slug: "vystavy-recamanova-struktura"
section: "vystavy"
date: 2024-01-01
thumbnail: "/images/vystavy-recamanova-struktura-nahled.jpg"
thumbnailAlt: "Recamánova struktura"
dateFrom: "1. 1. 2024"
dateTo: "31. 1. 2024"
city: "Jindřichův Hradec"
venue: "Muzeum fotografie a moderních obrazových médií"
exhibition: "Obrazy nad čísly"
draft: false
---
---
title: "Itálie - Benátky 2019"
slug: "cestovani-italie-benatky-2019"
section: "cestovani"
date: 2019-01-01
thumbnail: "/images/cestovani-italie-benatky-2019-nahled.jpg"
thumbnailAlt: "Itálie - Benátky 2019"
year: "2019"
media: "Fotografie"
draft: false
---
The following file was provided as a representative example of an MDX article:
recamanova-posloupnost-zelvi-grafice.mdx
This file is suitable as a reference example of content structure, frontmatter, and component usage.
ImageFigure.astroA component for standalone images with support for the following parameters:
srcaltcaptionwidthalignborderedlinkSupported width variants:
fullhalfone-thirdSupported alignment options:
leftcenterrightDepending on the configuration, the component can also open the image when clicked.
MediaRow.astroA component for arranging multiple items in a row. Supports the following types:
imagepdftextUse cases:
The component also supports a bordered variant.
Embed.astroA generic wrapper for embedded iframe content. It is used, for example, for:
Supported parameters:
srcratiokindwidthalignMediaRowWhen the grid collapses, a PDF iframe may require special adjustment of height or aspect ratio. This was handled using CSS for .media-row__pdf.
Listings and media layouts have multiple states depending on screen width. Some elements, such as the “show all” button or PDF embeds, required separate behavior adjustments for 3, 2, and 1 column layouts.
The homepage combines content from multiple parts of the website.
Each main section on the homepage displays the latest 9 items:
If a given section contains more items than the number displayed on the homepage, a “show all” tile is added.
The Propagační videa section uses a visual model similar to article listings, but the items link to external YouTube URLs. The listing is based on the videos collection.
Section headings on the homepage are clickable and serve as quick navigation to the relevant categories or an external playlist.
The homepage also contains specialized content blocks outside the standard article system:
npm install
npm run dev
Astro normally starts the local server at http://localhost:4321/ and reacts continuously to changes in the project.
In this specific project, it sometimes happens that after adding a new .mdx file, the new article does not appear correctly in dev mode, or temporarily replaces another article in the listing. Restarting the development server usually fixes it immediately.
Recommended troubleshooting step:
Ctrl + C
npm run dev
npm run build:web
Creates the standard build intended for normal deployment to web hosting.
npm run preview
Used for local verification of the production build.
npm run build:usb
This build is suitable, for example, for offline use, archiving, or transfer as a set of files.
build:usb logicThe build:usb script is defined as:
set "BUILD_TARGET=usb" && astro build && node scripts/usb-rewrite.mjs
This implies three steps:
BUILD_TARGET=usb is setastro.config.mjsscripts/usb-rewrite.mjs postprocessing script is executedastro.config.mjs does in this modeWhen BUILD_TARGET=usb, the following are used:
trailingSlash: "never"build.format: "file"This means that internal routes are generated as files of the form:
slug.html
instead of the directory form:
slug/index.html
scripts/usb-rewrite.mjs doesThe script:
.html files in the dist directorySpecific rewrites:
/_astro/ → ./_astro//images/ → ./images//files/ → ./files//demos/ → ./demos// → ./index.html/slug/ → ./slug.htmlThe purpose of this step is to adjust the HTML so that the output works even outside a standard web server with root-relative URLs.
dist structureThe dist/ directory contains the finished build intended for publishing.
For the production website, the content corresponding to the standard web build is uploaded to the hosting server.
.htaccessFor a static Astro website, a minimalist configuration is appropriate. A typical WordPress rewrite rule to index.php is not relevant for this type of project.
The portable build can be used as a file-based snapshot or offline copy. However, it is not identical to normal web hosting, and some external services may behave differently.
A YouTube iframe may fail in local or file-based mode with error 153. In that case, it is recommended to account for a fallback opening of the video via an external link.
The Sketchfab iframe may generate console warnings such as:
If the viewer works, this is not a project error, but a limitation or behavior of a third party.
If the build uses root-relative paths in an environment where no standard server root is available, styles, images, and internal links may break. For this reason, the portable file-based build is supplemented with the usb-rewrite.mjs postprocessing step.
If the listing or routes do not match after adding a new .mdx file, the recommended first step is to restart the development server.
Possible future directions for the project:
The project is designed as a file-oriented static website. Content is versioned directly in the repository, and the final published form is produced by the build process. This model makes it easier to archive, restore, and migrate the project without relying on a database runtime.
From a maintenance perspective, the following points are especially important:
.mdx filesThis documentation describes the current architecture and operating model of the project in a form suitable for ongoing maintenance, handoff, or future migration.