docs: rewrite README for the Earth Walker site
Replaces the boilerplate's generic stack-and-versioning notes with project-specific deployment guidance: routes, env vars, the inquiry-delivery flow (so future maintainers understand the Nostr plumbing isn't optional), image discipline (the anonymity rule plus the imagemagick incantation that normalizes new assets), and the add-a-project recipe. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
533e94352f
commit
d9f52c6e7b
1 changed files with 103 additions and 55 deletions
148
README.md
148
README.md
|
|
@ -1,74 +1,122 @@
|
|||
# boilerplate-website
|
||||
# Earth Walker Design
|
||||
|
||||
Opinionated Vue 3 starter — the base every new aiolabs website forks from.
|
||||
Studio site for an interior designer. Vue 3 + Vite + shadcn-vue +
|
||||
Tailwind 4. Anonymous-by-default contact: inquiry submissions are
|
||||
encrypted in the visitor's browser and delivered to the designer's
|
||||
Nostr inbox.
|
||||
|
||||
## Stack
|
||||
## Routes
|
||||
|
||||
- **Vue 3.5** + **Vite 8** + **TypeScript 6**
|
||||
- **shadcn-vue** (via `reka-ui` + `class-variance-authority` + `tailwind-merge`) — components.json pre-wired, run `pnpm dlx shadcn-vue@latest add <name>` to copy components in
|
||||
- **Tailwind CSS 4** (via `@tailwindcss/vite` — no `tailwind.config.js`)
|
||||
- **Pinia 3** — sample `useCounterStore` in `src/stores/`
|
||||
- **Vue Router 5** — file in `src/router/index.ts`, lazy-loaded views in `src/views/`
|
||||
- **Vue I18n 11** — `src/i18n/locales/{en,es}.json`
|
||||
- **vee-validate 4** + **zod 3** — form validation primitives (zod pinned to ^3 until `@vee-validate/zod` ships a v4-compatible resolver)
|
||||
- **@lucide/vue** — icon set (`lucide-vue-next` is deprecated upstream)
|
||||
- **ESLint 10** (flat config) + **Prettier 3**
|
||||
| Path | Purpose |
|
||||
|---|---|
|
||||
| `/` | Hero, studio voice, two project teasers, inquiry CTA |
|
||||
| `/portfolio` | Two-up project grid (Boulder, Asheville) |
|
||||
| `/portfolio/boulder` | Boulder project detail — editorial image scroll + lightbox |
|
||||
| `/portfolio/asheville` | Asheville project detail |
|
||||
| `/contact` | Inquiry form (Nostr-delivered) |
|
||||
|
||||
## Quick start
|
||||
## Local dev
|
||||
|
||||
```sh
|
||||
pnpm install
|
||||
pnpm dev # vite dev server
|
||||
pnpm build # type-check + production build
|
||||
pnpm preview # serve dist/
|
||||
cp .env.example .env # fill in VITE_OWNER_NPUB
|
||||
pnpm dev # http://localhost:5173
|
||||
pnpm build # type-check + production build to dist/
|
||||
pnpm preview # serve dist/
|
||||
pnpm lint
|
||||
pnpm format
|
||||
```
|
||||
|
||||
## Layout
|
||||
The contact form requires `VITE_OWNER_NPUB` to be set — without it,
|
||||
`submitInquiry` throws so visitors see an explicit error rather
|
||||
than silently dropping submissions. Generate one with
|
||||
[`nak key generate`](https://github.com/fiatjaf/nak) or any Nostr client.
|
||||
|
||||
```
|
||||
src/
|
||||
├─ App.vue # router-view shell
|
||||
├─ main.ts # plugin wiring
|
||||
├─ style.css # tailwind + shadcn-vue CSS variables
|
||||
├─ lib/utils.ts # cn() — shadcn-vue's class merger
|
||||
├─ router/index.ts
|
||||
├─ stores/counter.ts # example pinia store
|
||||
├─ i18n/
|
||||
│ ├─ index.ts
|
||||
│ └─ locales/{en,es}.json
|
||||
├─ views/HomeView.vue # proof-of-wiring page (i18n + pinia + tailwind)
|
||||
└─ features/
|
||||
├─ nostr/README.md # opt-in: nostr-tools wiring (see file)
|
||||
└─ lnbits/README.md # opt-in: LNbits payments wiring (see file)
|
||||
```
|
||||
## Env vars
|
||||
|
||||
## Optional features
|
||||
| Var | Required | Default | Notes |
|
||||
|---|---|---|---|
|
||||
| `VITE_OWNER_NPUB` | yes | — | The designer's Nostr public key (`npub1…`). Inquiries are NIP-17 gift-wrapped to this key. |
|
||||
| `VITE_NOSTR_RELAYS` | no | `wss://relay.damus.io,wss://nos.lol,wss://relay.nostr.band` | Comma-separated wss:// list. Submission succeeds if any one relay accepts. |
|
||||
|
||||
Both nostr and LNbits live as **documentation-only** folders. The deps
|
||||
aren't installed by default — bundle stays small for sites that don't
|
||||
need them. Each folder's README walks you through enabling.
|
||||
Both are inlined at build time by Vite. Rotating either requires a
|
||||
rebuild + redeploy.
|
||||
|
||||
- **`src/features/nostr/`** — connect to relays, sign/publish events, contact forms that DM the site owner's npub
|
||||
- **`src/features/lnbits/`** — create invoices, accept Lightning payments via an LNbits instance
|
||||
## How the contact form delivers inquiries
|
||||
|
||||
## Versioning strategy
|
||||
1. Visitor fills the form (name optional, contact method + value,
|
||||
message). Validation runs client-side via `vee-validate` + `zod`.
|
||||
2. `submitInquiry()` (`src/features/nostr/submitInquiry.ts`):
|
||||
- generates a fresh ephemeral secp256k1 keypair
|
||||
- decodes `VITE_OWNER_NPUB` to hex
|
||||
- calls `nip17.wrapEvent()` to produce a kind:1059 gift-wrap with
|
||||
NIP-44 v2 encryption inside (the visitor's identity is the
|
||||
throwaway key, not anything they entered)
|
||||
- publishes via `SimplePool` to the configured relays in parallel
|
||||
3. The designer receives the inquiry as a DM in any NIP-17 capable
|
||||
Nostr client (Damus, Amethyst, 0xchat, etc.) signed in with the
|
||||
matching nsec.
|
||||
|
||||
The boilerplate's `main` branch is **the "tools wired, no content" baseline**. New site = clone (or fork on Forgejo) → start adding content immediately.
|
||||
No server in between stores the message. There is no inbox to leak.
|
||||
|
||||
To pull dep refreshes from the boilerplate into an existing site:
|
||||
## Theming
|
||||
|
||||
Light + dark stone-warm palettes live in `src/style.css` as OKLCH
|
||||
CSS variables. Toggle persists to `localStorage` under
|
||||
`ewd:theme` (see `src/composables/useTheme.ts`). Typography pairs
|
||||
Fraunces (display, h1–h3, brand wordmark) with Inter (UI/body) via
|
||||
Bunny Fonts, declared in `index.html` and bound through Tailwind 4
|
||||
`@theme` directives.
|
||||
|
||||
To recolor: edit the OKLCH triples in `src/style.css` under `:root`
|
||||
and `.dark`. Keep all shadcn-vue token names intact.
|
||||
|
||||
## Image discipline
|
||||
|
||||
All images live under `public/images/<project>/`. The build pipeline
|
||||
expects:
|
||||
|
||||
- Filenames are sequence-numbered (`01.jpg`, `02.jpg`, …) — never
|
||||
leak addresses, neighborhood names, or owner identities in the
|
||||
filename.
|
||||
- EXIF / GPS / timestamp / maker metadata is stripped before commit.
|
||||
Re-run on new assets:
|
||||
```sh
|
||||
nix-shell -p imagemagick --run \
|
||||
'for f in *.jpg; do magick "$f" -auto-orient -strip -resize "2400x2400>" \
|
||||
-interlace Plane -sampling-factor 4:2:0 -quality 82 "${f}.tmp" \
|
||||
&& mv "${f}.tmp" "$f"; done'
|
||||
```
|
||||
- Alt text in `src/data/projects.ts` describes the room/feature, not
|
||||
the location.
|
||||
|
||||
## Adding a project
|
||||
|
||||
1. Drop sequence-numbered images into `public/images/<slug>/`.
|
||||
2. Add a new `Project` entry in `src/data/projects.ts` (typed) with
|
||||
`slug`, `name`, `eyebrow`, `intro`, `cover`, `coverAlt`, and an
|
||||
`images[]` array. Each image takes a `feature` tag
|
||||
(`hero` | `wide` | `narrow` | `paired`) that drives the layout
|
||||
slot in `ProjectDetail.vue`'s editorial scroll.
|
||||
3. Add a 4-line view at `src/views/projects/<Slug>View.vue`:
|
||||
```vue
|
||||
<script setup lang="ts">
|
||||
import ProjectDetail from '@/components/projects/ProjectDetail.vue'
|
||||
import { mySlug } from '@/data/projects'
|
||||
</script>
|
||||
<template><ProjectDetail :project="mySlug" /></template>
|
||||
```
|
||||
4. Register the route in `src/router/index.ts`.
|
||||
5. The `PortfolioView` already iterates `projects[]`, so the new
|
||||
project's card appears automatically.
|
||||
|
||||
## Stack
|
||||
|
||||
Tracking the upstream boilerplate (`aiolabs/boilerplate-website`).
|
||||
To pull dependency refreshes:
|
||||
|
||||
```sh
|
||||
git remote add boilerplate forgejo@git.atitlan.io:aiolabs/boilerplate-website.git
|
||||
git fetch boilerplate
|
||||
git merge boilerplate/main
|
||||
```
|
||||
|
||||
When a site diverges enough to no longer benefit from these merges, drop the remote — it becomes its own thing.
|
||||
|
||||
## Keeping deps current
|
||||
|
||||
- The boilerplate gets dep bumps via PRs (Renovate / Dependabot configurable; otherwise periodic `pnpm update --latest` + manual review).
|
||||
- The Vue ecosystem (vue, pinia, router, i18n, vee-validate) versions in lockstep — when one majors, the others usually follow within weeks.
|
||||
- Tailwind 4 + shadcn-vue + reka-ui is the current modern combo. shadcn-vue uses tw-animate-css (not the deprecated tailwindcss-animate plugin).
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue