at.ncvp.me

First Astro project with 'pages' and 'posts' collections

Astro js web framework

Experiment with Astro → GitHub → Cloudflare web deployment
~/winxp/projects/astro-test
GitHub: ncvp/astro-test
Cloudflare: cornett1610@gmail.com
Web: astro-test.ncvp.me

See also

.doc to .md conversion

Git notes

GitHub notes

ncvp block theme

ncvp theme, original

Node.js notes

VScode general

Website

Website menus

WordPress

Wordpress block themes

Wordpress git-cloud project

WordPress menu code

WordPress themes

Contents

404

astro-blog

Build

Change site URL

Cloudflare

Command line interface

Config

Content source possibilities

Conversions to try

Deployment via GitHub

Deployment via Wrangler

Dev server

Directories

.docx to .md conversion

Fancybox

Frontmatter

fuse.js

Galleries

GitHub

Image gallery

Install

IONOS

Key files

Keystatic

MDX

Menu

Pages & posts

Preview

Project tree restructure

React

Rebuild

Remove endpoint from built site

Routing

RSS

Search

Setup

Sites

Sitemap

Textflow

WordPress as front end

WordPress block pages

Wordpress conversion

WordPress media library

IONOS

Create astro-test.ncvp.me subdomain.
Add CNAME record specified by Cloudflare. Host name - astro-test, Points to - astro-test-8ol.pages.dev
Delete all other DNS records. IONOS may leave a spurious A record.

Top

GitHub

Create ncvp/astro-test private repo.
Connection between Cloudflare and GitHub is automatically achieved when setting up Cloudflare.
Connection between local PC and GitHub
% git remote add origin git@github.com-ncvp:ncvp/astro-test

Top

Cloudflare

There were some subtleties in setting up the project.

The project is ‘Pages’ not ‘Workers’. Dashboard should hav a url like this dash.cloudflare/…/pages/view/… AI said this was required for simple DNS change from IONOS which didn’t affect anything other than astro-test.ncvp.me

Build settings: Build command - npm run build, Build oputput directory - /dist

Top

Install

Basic

% cd ~/winxp/projects/astrojs
% npm create astro@latest
Where install: ./astro-test
Start with basic, helpful starter project
Initialise a new Git repository: yes

Extensions

% npm install @fancyapps/ui
% npx astro add mdx

Git

% cd astro-test
% git remote add origin git@github.com-ncvp:ncvp/astro-test
% git branch -M main
% git commit -m “Initial Astro setup”
% git push -u origin main

Top

Dev server

Shows state in browser as it is modified
% cd ~/winxp/projects/astro-test
% npm run dev

Top

Build

Prepare site for production
% cd ~/winxp/projects/astro-test
% npm run build

Leave out

Top

Preview

Preview build locally before deploying
% cd ~/winxp/projects/astro-test
% npm run preview

Top

Deployment via GitHub

% cd ~/winxp/projects/astro-test
% git push -u origin main

Top

Deployment via Wrangler

astro-local & astro-wpress

Normal Cloudflare deployment doesn’t work with local WP because Cloudflare can’t get at local site. GitHub is not needed.

You can’t use the normal Cloudflare build mechanism, but have to build locally and upload /dist

Install Cloudflare CLI tool (Wrangler)
% npm install -D wrangler

Connect to Cloudflare account
% npx wrangler login

Build Astro site locally
% npm run build

Upload complete site to Cloudflare
% npx wrangler pages deploy dist

Adding this to package.json
”deploy”: “npm run build && wrangler pages deploy dist”,
allows
% npm run deploy # Build and deploy in one command

Deployment failed, 8 Jun 26

Authentication error.
Gemini seemed to think this was not unusual
% npx wrangler login
Follow instructions
Successfully logged in

% npm run deploy # Worked

It is possible to deploy the media library direct to Cloudflare and get CF to do the build, but above method works, and seems simpler

Top

Sitemap

Follow this Astro doc

Nothing happens locally. Possibly because it hasn’t been built yet by Cloudflare.

Top

Fancybox

fancyapps.com/fancybox/api/options

Carousel API options

Options difficult to find. Ask AI

Install with npm
% cd ~/winxp/projects/astro-test
% npm install @fancyapps/ui

Add
<script>
import { Fancybox } from “@fancyapps/ui”;
import “@fancyapps/ui/dist/fancybox/fancybox.css”;
Fancybox.bind(“[data-fancybox]”, {});
</script>
to end of <body> in Layout.astro

It can also be installed via its CDN, but why would one?

Top

Wordpress conversion

Export all content from WP site to ~/winxp/projects/wordpress/export/xxxx

% npx wordpress-export-to-markdown # Invokes wizard
GitHub page
Options:

Quite a few images in gallery 3 from several-galleries were not downloaded.
They were in the XML file, but the tool did not download them.
Lots of them had a localhost URL in their <guid> tags. Even when I changed these strings to the correct site url and reran the tool it still missed the images.

Construct gallery HTML with
% wp_gall_ext xml-file-path

Top

Project tree restructure

% md ~/winxp/projects/astrojs
% mv ~/winxp/projects/astro-test ~/winxp/projects/astrojs/astro-test
% cd ~/winxp/projects/astrojs/astro-test
% npm run dev # Worked normally
% git push -u origin main # Worked normally
Browse https://astro-test.ncvp.me # Worked normally

Top

astro-blog

Create GitHub private repo ncvp/astro-blog

% cd ~/winxp/projects/astrojs
% npm create astro@latest
./astro-blog, blog template, create Git repo
% cd astro-blog
% git remote add origin git@github.com-ncvp:ncvp/astro-test
% git branch -M main
% git commit -m “Initial Astro setup”
% git push -u origin main
% npm install @fancyapps/ui

Cloudflare
Had to configure GitHub to allow connection to ncvp/astro-blog
Build settings: Build command - npm run build, Build oputput directory - /dist

IONOS
Create astro-blog.ncvp.me
Create CNAME record as specified by Cloudflare. All other records deleted automatically.

Top

Config

Remove toolbar at bottom of screen

Add devToolbar: {enabled: false}, to astro.config.mjs

Top

Routing

This is Astro’s term for mapping site-url/slug to page file.

Astro routing reference is not very helpful with specifics

Basics

Fairly obvious
site-url/xxxx → project/src/pages/xxxx.astro, or xxxx.md

Slightly subtle
site-url/xxxx/→ project/src/pages/xxxx/index.astro, or xxxx.md
Confusing in the sitemap. Don’t use index.yyyy except where required, ie src/pages/index.astro

Blog

Individual posts are xxxx.md files in src/content/blog accessed via site-url/blog/xxxx.
This scheme can presumably be extended if we get thousands of posts, but it should be good enough for me.

Lists

site-url/blog list all posts

site-url/blog/category/xxxx lists all posts in category xxxx.
This is done

Similarly author.

Tags could be implemented in the same way.

Weird directory/file names

site-url/slug Astro file
/yyyy/mm /src/pages/[year]/[month].astro
/author/xxxx /src/pages/author/[slug].astro
/category/xxxx /src/pages/category/[slug].astro
/tag/xxxx /src/pages/tag/[slug].astro
xxx/yyy

/src/pages/[slug].astro

Renders post xxx/yyy

xxx/yyy

/src/pages/[...path].astro

Renders page xxx/yyy

Top

404

All missing url’s come here. There’s supposed to be a mechanism for routing site-url/blog/category/invalid-slug to […category], for example, but Gemini couldn’t get it too work.

It’s quite easy to get 404.astro to deal with obvious stale links and mis-typings, and this is actually a better solution.

Top

Search

I thought initially that this would not be possible with a static site, but Astro has an ingenious solution. At build time it generates a compact index which the client only downloads if the search box is clicked.

% npm install fuse.js

src/pages/search.json.js

Includes getCollection() like rss.xml.js

Top

Conversions to try

The only website of mine that has real data is ncvp.co.uk/ngarden, and the connections with local WP site and Leaflet plans pages make it rather unsuitable.

echoandnarcissus.co.uk is a good candidate. It doesn’t have an ssl certificate, so would benefit with Cloudflare deployment. It’s completely static anyway. SEO could be tried. Possible route:

  1. Move coral.ncvp.net/echo-orig to ncvp.me/echo

  2. Develop astro-echo.ncvp.me

  3. Point echoandnarcissus.co.uk → Cloudflare

Top

Rebuild

% npm run build # Full rebuild for production using cache
% npx astro build —force # Clears cache before production build

% npx astro dev —force # Starts dev server bypassing the cache

Top

Command line interface

Astro docs

% npx astro —version

Top

Wordpress as front end

Follow this Astro article

Create src/pages/wpress.astro and src/pages/posts/[slug].astro in astro-test project. That works for posts, but doing the same for pages will interfere with the existing pages. Create a new project astro-wpress.

Special pages

/Home. Must be provided as src/pages/index.astro
/sitemapWP page rendered by shortcode. Astro page urls all point to https://ncvp.me/wp. Not easily replaced ‘cos my src/pages/sitemap is built by traversing tree of real files.
/blogReplacement src/pages/blog.astro seems to hide WP blog, whose urls are wrong anyway.
404Replacement src/pages/404.astro
/select-postsBlock page
/category/category-nameNot a WP page. Will need to be constructed
/tag/tag-name
/author/author-name

Special routing

/src/pages[…path].astro

Top

MDX

% cd astro-project-root
% npx astro add mdx

What are the advantages over MD. Are there any of my standard pages which can’t be expressed as MD

Top

Remove endpoint from built site

Sometimes it’s useful to have files like src/pages/all-pages.astro which are used in development but shouldn’t be part of the final site.
Change this line in /package.json
{

“scripts”: {

“build”: “astro build && rm -rf dist/all-pages”,

},

}
Presumably this will also affect the build that Cloudflare does.

Top

Directories

% tree . -dq —gitignore
.
├── public
├── scripts
└── src
├── assets
├── components
├── data
├── layouts
├── pages
│   ├── author
│   ├── category
│   ├── tag
│   └── [year]
├── styles
└── utils

public

Possibly need for favicon

scripts

Node.js scripts ‘outside’ Astro. eg get-menu.mjs which gets the menu in location header in astro-wpress

src/assets

Gemini recommends this should be used for ‘almost everything’
import alias @assets is set to point here

src/data

Where I keep all the menu definition files, including the ouptu of get-menu.mjs in astro-wpress

src/styles

Global astro-wpress.css in astro-wpress

src/utils

Helper JS utilities used in various Astro components

Top

RSS

% npm install @astrojs/rss

/astro.config.mjs

export default defineConfig({

site: ‘https://xxxx.ncvp.me\’, // Cloud URL

});

Layout.astro

Add to <head>
<link rel=“alternate” type=“application/rss+xml” title=“astro-wpress.ncvp.me” href={`${Astro.site}rss.xml`} />

/src/pages/rss.xml.js

Two sorts of posts fetch (so far). From local collection, and from WP REST API

Top

React

% npx astro add react

First needed for Gemini supplied MDX test page

Top

Change site URL

Create new subdomain at IONOS

In Cloudflare add the new custom domain to the Workers & Pages project

In Astro update the domain name in /astro.config.mjs
Change the site title in Header.astro
Change the url in src/pages/rss.xml.js

Gemini says I can keep old domain in Cloudflare and set up a Bulk Redirect, but I don’t need this with a new test site. Delete astro-blog.ncvp.me from CloudFlare and IONOS

Top

.docx to .md conversion

This is proving surprisingly difficult.

These are the features that need to be converted

pandoc and Mammoth fail with single <CR> in paragraph.

Test files in ~/winxp/projects/doc

test.docx
test1.docx

Utilities in ~/winxp/projects/doc

docx2astro.js and docx2html.js
Node.js projects using Mammoth and Turndown
Mildly interesting. Ultimately unusable because Mammoth can’t handle <CR>
Useful the way it writes the .md directly to an Astro post or page.

docx_to_astro.py

doc2md.py

docx_to_astro_md.py

docx_to_markdown_precise.py

Top

Keystatic

Looked promising for a while, but turned out to be unusable.
AstroEditor looked a bit crude, and only seemed to work on content collections.

Top

Menu

/scripts/get-menu.mjs gets the menu via the WP REST API and builds menu_definition_auto.js in /src/data
Check carefully against menu_definition.js and replace when OK

Add to package.json manually

“scripts”: {
“get-menu”: “node scripts/get-menu.mjs”,

Run with
% cd ~/winxp/projects/astrojs/astro-local
% npm run get-menu

Neat, but in practice it’s so simple to handcraft a menu and it’s changed so rarely it’s hardly worth bothering with the automated version.

Top

Setup

Copy /tsconfig.json from astro-wpress

Add
site: “https://al.ncvp.me\”,\ devToolbar: { enabled: false },
to astro.config.mjs. Rest of file slightly different with MDX stuff

Create a 70x70 logo, and put separately named copies in /public and /src/assets

Copy src/layouts/Layout.astro from astro-wpress and tweak

Copy src/components/Footer.astro, Header.astro, Menu.astro from astro-wpress and tweak

Copy src/styles/astro-wpress.css and rename astro-local.css

Copy src/data/menu_definition.js from astro-wpress

Copy src/pages/index.astro from astro-wpress and tweak. At this point Home page burst into life.

Copy src/utils from astro-wpress

Top

Content source possibilities (Gemini)

Other editorial possibilities

**1. Decoupled CMS (Headless)
**If you like the “dashboard” feel but want something more modern or specialized than WordPress, look at:

Payload CMS: This is currently the “darling” of the Astro community. It’s a Node.js-based headless CMS that is incredibly flexible. You can run it locally (just like WP) or host it. It uses TypeScript, so it integrates perfectly with your Astro constants and types.

Sanity.io: A cloud-based CMS where you define your “schema” (fields) in code. It has a great real-time editor and an Astro integration that makes fetching data very simple.

**2. Git-Based CMS (The “MD” Evolution)
**Since you’ve already worked with Markdown files, these tools provide a visual UI on top of your .md or .mdx files. They don’t need a database; they just commit changes to your Git repo.

Decap CMS (formerly Netlify CMS): An open-source classic. It adds an admin dashboard to your site that lets you write posts, and when you hit “Save,” it commits a Markdown file to your repo.

TinaCMS: This is the most impressive “modern” choice. It allows for Visual Editing, where you click on a heading directly on your Astro site and type to change it. It saves the changes back to your Markdown files.

**3. Keystatic (The “Local-First” Winner)
**Since you are currently enjoying a local-first workflow with Xubuntu and symlinks, you should definitely check out Keystatic.
It was built specifically for the “Astro/Next.js” era.
It has no database. It’s a beautiful UI that runs in your browser but saves everything as local files in your project.
It handles image uploads brilliantly---it will save them directly into your public/ folder without needing symlinks or rsync.

Comparison for a WP User:

FeatureWordPressKeystaticTinaCMS
Data SourceMySQL DatabaseLocal Markdown/JSONGit-based Markdown
InterfaceFamiliar / HeavyMinimal / CleanVisual / Live
ImagesMedia LibraryLocal FolderLocal Folder/Cloud
Astro SetupREST API FetchLocal File ImportGraphQL/Git

My Recommendation: If you want to stick with a “Local Build” workflow but want to get away from the overhead of a full PHP/MySQL WordPress install, try Keystatic. It gives you a clean editorial UI while keeping everything as simple files on your hard drive.

Top

Galleries

Vanilla classic galleries work fine.
Block galleries are useless. Don’t waste time on them.

Top

Sites

Astro static sites with content supplied by WordPress sites.

astro-wpress

Uses ncvp.me/wp for content

Downloads wp-content/uploads

astro-local

Uses localhost/wp/wp for content

Symlinks wp-content/uploads

astro-echo

Uses ncvp.me/echo for content

Media library remains at ncvp.me/echo

astro-wpress

Content supplied by ncvp.me/wp.
Media library downloaded to ~/winxp/projects/astrojs/astro-wpress/public/wp-content/uploads.
Deployment to Cloudflare via Wrangler.
Requires a media sync step in the build process.
No GitHub repo.
This method allows editorial input from several people in disparate locations.Should the source site be private? How?

astro-local

Content supplied by localhost/wp/wp.
Media library symlinked to ~/winxp/projects/astrojs/astro-local/public/wp-content/uploads
Deployment to Cloudflare via Wrangler.
Very straightforward connection.
No GitHub repo.

astro-echo

Weird issue with Blog page. Nothing happened until the block page was copied from one of the other sites, when it burst into life
Simpler setup. No categories or tags, so no special post lists required.Uses the cloud media library. Can’t be downloaded because at least half the pictures are not used on the site. Can they be deleted?
What’s the point of this sort of setup?

Top

WordPress block pages

All the pages are classic apart from the following:

Home

Nice arrangement of general notes in the left-hand column and recent news posts in the right-hand. Keep it because it just works in Astro and ncvp-class

Blog

I made this look like the RHS of the home page by copying the Home page and taking out the ‘General’ column. I had to leave the single column in place, however.

There was an oddity with astro-echo. Initially /blog produced nothing. But when I copied the Blog page from one of the other sites it sprang into life.

Select posts

I made this in the block editor for the category date and tag WP selector blocks. I had to make an [ncvp_author] shortcode because the author selector is missing in WP. This caused a lot of trouble (for Gemini) because WP scripts try to get in and hijack the links to /category/test etc. It may be less trouble to do the whole page with a classic shortcode.
The post search section at the bottom is hidden in CSS. It could never work. It’s replaced with src/pages/search-posts.astro

Top

Pages and posts

Apart from src/pages/search-posts.astro there are no pages or posts stored in the src tree. All pages and posts are retrieved from the WordPress REST API via these weird directory/file names:

site-url/slug Astro file
/yyyy/mm /src/pages/[year]/[month].astro
/author/xxxx /src/pages/author/[slug].astro
/category/xxxx /src/pages/category/[slug].astro
/tag/xxxx /src/pages/tag/[slug].astro
xxx/yyy

/src/pages/[slug].astro

Renders post xxx/yyy

xxx/yyy

/src/pages/[...path].astro

Renders page xxx/yyy

Top

WP media library

astro-local

Astro needs access to localhost/xxxx/wp-content/uploads to build the static site locally.
Do this with a symlink. This seems to survive Git and Wrangler deployment to Cloudflare.
~/winxp/projects/astrojs/astro-local/public/wp-content$ ls -l uploads
lrwxrwxrwx 1 ncvp ncvp 55 May 23 13:59 uploads -> /home/ncvp/winxp/apache/htdocs/wp/wp/wp-content/uploads

astro-wpress

Astro static site gets everything from ncvp.me/wp. Media files are downloaded (and synced) to /public/wp-content/uploads. This works well, but it isn’t a s neat as astro-local.

astro-echo

Astro static site currently gets media files from ncvp.me/echo. This is not ideal. It would be better to use Cloudflare like astro-local but only when the future of echo is decided.

Top

Image gallery plugin

Fancybox on Astro works well, and is version 5.

ncvp-image-gallery works fine with galleries with ncvp-class. Behaviour is very slightly different on localhost/wp/wp and astro-local. Nothing to be worth trying to fix.

Top

Text and images

Two textflow test pages on localhost/wp/wp both use hard-coded HTML. Much the best way. Don’t bother with anything else.

Top

Key files

/

astro.con.mjs
tsconfig.json --- defines paths to layouts, components, utils etc.

/public

Site logo
All images as .webp for sites with content in /src
/wp-content/uploads for sites sourced from WP sites

/scripts

constants.ts --- site url, WP REST API url etc.
get-menu.mjs --- automatic menu builder. Over the top

/src

content.config.ts --- defines posts collection as Zod schema
content --- defines posts and pages content collections
data --- menu definition
styles --- global stylesheet
utils --- post_helpers.js

Top

Frontmatter

Python script in ~/winxp/projects/astrojs/fmatter
Call with % fmatter from anywhere

Top