From d9f52c6e7b07bc3588cb6c1d7977670ddaa97f18 Mon Sep 17 00:00:00 2001 From: Padreug Date: Wed, 27 May 2026 11:26:18 +0200 Subject: [PATCH] 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) --- README.md | 148 ++++++++++++++++++++++++++++++++++++------------------ 1 file changed, 98 insertions(+), 50 deletions(-) diff --git a/README.md b/README.md index 977732b..defaaef 100644 --- a/README.md +++ b/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 ` 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//`. 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//`. +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/View.vue`: + ```vue + + + ``` +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).