Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 33 additions & 0 deletions .github/workflows/pr-checks.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
name: PR checks

on:
pull_request:

permissions:
contents: read

concurrency:
group: pr-checks-${{ github.event.pull_request.number }}
cancel-in-progress: true

jobs:
checks:
name: Vite+ checks
runs-on: ubuntu-latest
timeout-minutes: 15
steps:
- name: Check out the PR
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1

- name: Set up Vite+
uses: voidzero-dev/setup-vp@cab1ab9eaff52d4857875f4f2c016e36af8f2c76 # v1.22.0
with:
node-version: "24"
cache: true
run-install: false

- name: Install dependencies
run: vp install --frozen-lockfile

- name: Check formatting, lint and types
run: vp check
112 changes: 18 additions & 94 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,109 +1,33 @@
# ashfid.dev - digital garden
# ashfid.dev / ashfid.com

Personal website built with TanStack Start, React, MDX, Tailwind CSS, and shadcn-style UI primitives.
I'm Ashfid, a software engineer and game developer. This is my digital garden, where I share what I'm learning, write about games and their mechanics, and keep useful bits of code so I can find them again.

Site metadata, navigation, categories, tools, skill groups, and icon mappings are maintained in
`site.config.json`. Long-form posts remain in `src/content/posts` as MDX.
I wanted it to feel cozy and a little playful, so it lives inside a small terminal window with a pixel version of me. Pick a theme, browse the posts, or try a command in the prompt.

```bash
vp install
vp run dev
```

## Add a blog post

Create `src/content/posts/blog/my-post.mdx`. The filename becomes the URL, so this
example is published at `/blog/my-post`.

```mdx
---
title: My post title
description: A short summary used for search engines and link previews.
published_time: 2026-08-08
category: web
tags:
- website
- development
---
Visit the garden at [ashfid.dev](https://ashfid.dev) or [ashfid.com](https://ashfid.com).

Write the post here using Markdown.
Built with TanStack Start, React, MDX, and Tailwind CSS. Pages are generated ahead of time and hosted on Cloudflare.

## A section heading
## Run it locally

You can also import and use React components because post files use MDX.
```

`title`, `description`, `published_time`, `category`, and `tags` are required.
The category must match an ID in `site.config.json`. You can optionally add
`last_modified_time: YYYY-MM-DD`. Run `vp run check` and `vp run build` before
publishing to catch invalid frontmatter or MDX.

Every page includes Open Graph and X/Twitter metadata. The build generates 1200×630 PNG share
cards with Satori into `public/images/og` before TanStack Start prerenders the site. Posts get an
individual card automatically. To feature an image already in the repository, add these optional
frontmatter fields (paths are relative to the repository root):

```yaml
social_image: src/assets/images/posts/my-post/cover.jpg
social_image_alt: A concise description of the cover image
```
Fork or clone the repo, then run these from the project folder with Vite+ installed:

Run `vp run generate:og` to preview regenerated cards without building the entire site. Generated
PNGs are ignored by Git because both development and production build commands recreate them.

Image selection is predictable:

- General site pages use `public/images/android-chrome-512x512.png`.
- Posts with `social_image` use that image.
- Posts without `social_image`, including the current snippets, use the same site avatar fallback.
- `hello-world` currently uses `src/assets/images/posts/desktop_view.jpeg`.
- `final-fantasy-7-remake-review` currently uses
`src/assets/images/posts/final-fantasy-7-remake/final-fantasy-7-remake-01.jpg`.

Posts in the `game-review` category also require review details. These appear as a prominent score
and facts panel below the post title.

```yaml
review:
rating: 4
platform: PC
playtime_hours: 23.4
status: Finished
```sh
vp install
vp run db:migrate:local
vp run dev
```

Useful commands:

- `vp run check`: type-check the project
- `pnpm run build`: reject legacy Pages builds, build every route, and verify the Worker bundle
- `pnpm run deploy`: deploy the verified bundle with Wrangler
- `vp preview`: preview the production build locally

## Cloudflare Workers
Open [localhost:3000](http://localhost:3000). The database step sets up local storage for post likes; you only need it on the first run or when the database changes.

This is a TanStack Start Worker with prerendered static assets, D1, and a rate-limit binding. It must
be deployed as a Worker; a Pages static upload cannot run the server functions or rate limiter.
## Make it yours

Configure Workers Builds with:
Start with [site.config.json](site.config.json) for your name, links, tools, and skills. Posts and snippets live in [src/content/posts](src/content/posts). Copy an existing MDX file to get started; its filename becomes the URL.

- Production branch: `main`
- Build command: `pnpm run build`
- Deploy command: `pnpm run deploy`
- Root directory: `/`
Swap out my images and branding, and change whatever you like. If you're deploying your own copy, update [wrangler.jsonc](wrangler.jsonc) with your Cloudflare settings too. `vp run build` creates the production build.

The Cloudflare Vite plugin generates `dist/server/wrangler.json`, which points Wrangler at the
Worker entry in `dist/server` and the assets in `dist/client`. Do not upload either directory to
Pages manually. The build fails if it detects the Pages environment, a missing Worker bundle, a
stale root `dist/index.html`, an old `/_astro/` reference, or a missing generated asset.
## Contributing

For a manual release, run:

```bash
pnpm run check
pnpm run build
pnpm run deploy
```
Found a bug or have an idea? Open an issue or send a pull request. For bigger changes, start an issue so we can talk it through first.

Test the generated `workers.dev` URL before moving the production custom domains. Once the Worker is
verified, remove `ashfid.dev` and `www.ashfid.dev` from the legacy Pages project and attach them to
the Worker. The legacy Pages Git integration should then be disabled or deleted so a push cannot
publish a second deployment target.
You're welcome to fork this and build your own garden. It's available under the [MIT license](LICENSE).
15 changes: 0 additions & 15 deletions components.json

This file was deleted.

32 changes: 0 additions & 32 deletions docs/research/2026-08-17-vite-plus-tanstack-start.md

This file was deleted.

6 changes: 1 addition & 5 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,14 +30,10 @@
"@tanstack/react-query": "^5.101.4",
"@tanstack/react-router": "^1.170.23",
"@tanstack/react-start": "^1.168.40",
"clsx": "^2.1.1",
"cmdk": "^1.1.1",
"@tanstack/redact": "^0.2.3",
"drizzle-orm": "^0.45.2",
"fuse.js": "^7.5.0",
"lucide-react": "^0.539.0",
"react": "^19.2.0",
"react-dom": "^19.2.0",
"tailwind-merge": "^3.3.1",
"use-lanyard": "^2.0.0",
"zod": "^4.0.17"
},
Expand Down
86 changes: 27 additions & 59 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading
Loading