尚未检测到更新。GitHub 发布版本后会显示在这里。
个人 GitHub 账号下公开仓库的所有者可以登录并验证所有权,自行管理介绍,无需管理员批准。
登录并生成验证文件,在 30 分钟内将其提交到此仓库的默认分支。其他分支或分叉仓库中的文件无效。然后在下方检查文件,即可无需管理员批准直接管理项目。请保留文件以维持管理权限。
如需登录,将前往登录页面。登录后请回到此处,再次点击所选的验证按钮。
在项目文件夹中运行 /nomorevibe verify,即可验证所有权并自行管理介绍。
一分钟完成验证Travel blog
翻译准备中
取自仓库 README
正在加载完整 README。 以下为已保存的摘录。
Welcome to the Daniela and Will Travel Blog repository! This project contains the
source code for our travel blog, where we share our travel experiences, tips, and
guides.
Built with Astro and deployed to GitHub Pages.
Directory nesting under a language (asia/, europe/, tools/) is
organisational only — it never appears in the URL.
2. Install dependencies — requires Node.js 22 or newer.
3. Run the development server at.查看完整 README ↗Welcome to the Daniela and Will Travel Blog repository! This project contains the source code for our travel blog, where we share our travel experiences, tips, and guides.
Built with Astro and deployed to GitHub Pages.
public/ Served verbatim at the site root
assets/files/ Downloadable budget + planning spreadsheets
assets/fonts/ Self-hosted webfonts
assets/img/ App icons and the default Open Graph image
favicon.ico
src/
assets/img/ Photography — optimized at build time by astro:assets
components/ Reusable markup (Figure, Card, Navigation, Footer, …)
styleguide/ Story + Swatch, used only by /styleguide/
content/posts/<lang>/ Blog posts as .mdx, organised by region
data/ Settings, locales, navigation, translations
layouts/ Base, Page, Post
lib/ Dates, reading time, tags, i18n, image resolution
pages/ Routes (see below)
plugins/ Markdown pipeline extensions
scripts/ The site's client-side JavaScript
styles/ The CSS design system
content.config.ts Content collection schemas
| Route | Source |
|---|---|
/ | src/pages/index.astro |
/en/<page>/ | src/pages/en/<page>.astro |
/en/writing/<slug>/ | src/content/posts/en/**/<slug>.mdx via src/pages/[...slug].astro |
/<lang>/tag/<tag>/ | src/pages/[lang]/tag/[tag].astro, generated from post tags |
/<lang>/feed/feed.xml, .json, .xsl | src/pages/[lang]/feed/ |
/sitemap.xml, /robots.txt, /humans.txt | src/pages/*.ts |
Directory nesting under a language (asia/, europe/, tools/) is
organisational only — it never appears in the URL.
Clone the repository
git clone https://github.com/daniela-and-will-travel/daniela-and-will-travel.github.io.git
cd daniela-and-will-travel.github.io
Install dependencies — requires Node.js 22 or newer.
npm install
Run the development server at http://localhost:4321.
npm run dev
Build the production site into dist/.
npm run build
| Command | What it does |
|---|---|
npm run dev | Dev server with hot reload. Draft posts are visible here. |
npm run build | Production build. Drafts are excluded. |
npm run preview | Serve the built dist/ locally. |
npm run check | Type-check components and validate every post against the schema. |
npm test | Run the regression tests against dist/. Build first. |
npm run clean | Remove dist/ and the build caches. |
npm test runs against the built output rather than the source, because what it
guards only exists after a build. See tests/theme-persistence.test.mjs: Astro's
ClientRouter strips every attribute off <html> on a soft navigation, which
destroys the data-theme the theme script sets at runtime. The repaint that
fixes it lives in src/scripts/site.ts and is invisible to both the type check
and the build, so it needs a test.
The first build re-encodes every photograph and takes a few minutes. Later
builds reuse the cache in node_modules/.astro and take seconds; CI restores
that cache between runs.
Posts are .mdx files under src/content/posts/<lang>/. Front matter is
validated by the schema in src/content.config.ts, so a missing or misspelled
key fails the build rather than quietly producing a broken card.
---
title: One Week Japan Itinerary
date: 2025-03-10
author: Daniela
tags:
- asia
- southeast-asia
- japan
- itinerary
- planning
draft: false
byline: How to visit Japan on a bougie backpacker budget!
heroImage: /assets/img/posts/asia/IMG_0495.jpg
heroImageAlt: A street scene in Japan
seo:
title: One Week Japan Itinerary
description: How to visit Japan on a bougie backpacker budget!
---
title, date, tags, byline, heroImage and heroImageAlt are required —
the last three are what make a post look right in the card grids on the home
page, the countries page and the related-posts strip. seo is optional; set
seo.slug to override the URL slug, which otherwise comes from the filename.
modified is optional and deliberately so. It feeds dateModified in the
post's JSON-LD and lastmod in the sitemap, so only add it when the content
actually changed — refreshed prices, a new visa rule, a rewritten section.
Omitted, both fall back to date, which is the honest answer for a post that
has never been revised. Don't mirror date into it; the schema rejects a
modified earlier than date. It is not derived from the filesystem on
purpose: actions/checkout stamps every file with the clone time, and a git
last-commit date moves for build-only commits, so either would announce a
refresh that never happened.
Static pages under src/pages/ export a meta object that the sitemap reads.
Set lastModified (an ISO date) when you change one — it becomes the URL's
<lastmod>, the one sitemap hint Google actually reads. It is declared rather
than derived for the same reason modified is on posts: the build time would
claim every page changed on every deploy, and actions/checkout stamps the
whole tree with the clone time. <priority> and <changefreq> are not emitted
at all — Google ignores both, and every page here had declared priority 1.0,
which makes a relative signal say nothing.
Every tag becomes an archive page at /<lang>/tag/<tag>/ automatically. Add a
display override to TAG_LABEL_OVERRIDES in src/lib/format.ts for any tag
that doesn't survive plain title casing (vpn → VPN). A tag holding fewer
than MIN_INDEXABLE_TAG_POSTS posts (src/lib/posts.ts, currently 3) still
gets a page, but it is served noindex, follow and kept out of the sitemap — a
one-post archive is a near-duplicate of the post it lists and competes with it.
Tags cross the threshold on their own as posts accumulate.
Tags also drive the related-posts strip: it recommends the three posts sharing the most tags with the current one, spreading links so no post is left without inbound links. Tagging accurately is what makes that work.
Put photographs in src/assets/img/ and reference them by their published path:
import Figure from '@components/Figure.astro';
<Figure
src="/assets/img/posts/asia/komodocover.jpg"
alt="Aerial shot of islands surrounded by beaches and blue water"
sizes="100vw"
caption="Beautiful aerial shot of the Komodo Islands"
/>
Figure generates AVIF, WebP and original-format variants at several widths.
Passing a caption also renders the Shutterstock photo credit chip — it is
an affiliate placement, so don't skip the caption on our own photographs.
Images lazy-load by default. The first Figure in a post must carry
priority — it is the one above the fold, and a lazy image isn't discovered
until layout decides it is near the viewport, which is exactly what makes it a
slow Largest Contentful Paint. priority sets loading="eager" and
fetchpriority="high" together. Use it on exactly one image per page; marking
several is the same as marking none, because they compete with each other.
npm test fails the build if a post's hero isn't eager.
Files in public/ are copied as-is and are not optimized; that folder is for
icons, fonts and downloads only.
Two blockquote markers become styled notice boxes:
> ❕ Tip: Arrive at least one day before with enough time to get sorted.
> ⚠ Warning: The park entry fee is not always included in the tour price.
Note and Tip render as an info box, Warning as a warning box. The
transform lives in src/plugins/notices.js.
The blog runs on a token-driven CSS design system — no framework, no utility classes. Everything visual resolves back to a custom property, so dark mode and future tweaks stay cheap.
src/styles/variables.css — design tokens: brand palette, semantic colours,
type scale, spacing, radii, shadows, motion. Add new values here rather than
hard-coding them in a component.src/styles/reset.css — modern reset.src/styles/styles.css — element defaults, layout shells (.shell,
.section, .grid) and shared utilities.src/styles/components/*.css — one file per component.src/styles/main.css — imports the above. New component files must be added
here.A living style guide is published at
/styleguide/
(src/pages/styleguide.astro). Every example on that page is rendered with the
real stylesheet and shown next to the markup that produced it, so it never
drifts from the site.
Check it before building a new page, and add a story when you add a component:
const myMarkup = `
<a class="button" href="#">Browse destinations</a>
`;
<Story label="Label" markup={myMarkup} note="optional note" />
The same string is rendered live and printed as source.
The site is built bilingual (English and Spanish). Interface strings live in
src/data/translations.ts — never hard-code UI text in a component. A lookup
that misses throws during the build, so the two language trees can't silently
drift apart.
Spanish currently has no content. The machinery is in place: add
src/pages/es/<page>.astro or src/content/posts/es/<slug>.mdx and the
language switcher, hreflang tags, feeds and manifest pick it up automatically.
Until then no hreflang is emitted at all, by design: a set naming only the
page it sits on is self-referential and tells a crawler nothing the canonical
doesn't. The moment a page has a translation it gets the full set — both
languages plus x-default — because a partial set is ignored wholesale.
Pushing to main triggers .github/workflows/static.yml, which type-checks,
builds and deploys to GitHub Pages. Pull requests are built but not deployed.
We welcome contributions! If you find a bug or have a suggestion, please open an issue or submit a pull request.
The code in this project is licensed under the GNU General Public License v3.
See the LICENSE file for details. The copyright of the text on the blog is that
of the respective author.
Questions or suggestions relating to development of the travel blog can be brought up through an open issue. All other inquiries, including licensing and partnership inquiries, should be handled through the contact form on the blog itself.