diff --git a/AGENTS.md b/AGENTS.md index 8fe1798..ae4a303 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -806,18 +806,18 @@ session with **no other memory of this project**. So: burger menu (`MOBILE_MENU_LISTED_HREFS`) now **appends catalog items that aren't hard-coded**, so Marketplace/Mints (and any future section) are always reachable on mobile — don't re-hardcode only a subset. -- **DIY resources (`/diy`, 2026-10-05):** a curated hub for making your own +- **DIY resources (`/diy`, 2026-10-05):** a hub for making your own boards/ramps/concrete. Content is a seed list in **`src/lib/diyGuides.ts`** (`DIY_CATEGORIES` boards/ramps/concrete/repairs/tools + `DIY_CARDS` + - `DIY_ACTIONS`) — vetted external links (Open Source Skateboards / SK8CAD / - Instructables / YouTube) and in-app action cards; rendered by - `src/pages/DiyPage.tsx`. Registered as a nav-catalog item (id `diy`, Hammer) - so it shows in the desktop "More" menu **and** the mobile burger, and linked - from the **site footer** + the **map links strip**. Cross-links OUT to - `/lab?craft=building` (Builder), `/crews`, `/create-spot`, `/create-listing`, - `/lab?craft=coaching`. ⚠️ **Link out, never rehost** — credit the source; - `sanitizeUrl` on every external URL. In-app tools (cost calculator) are the - next step; community guides would be NIP-23 `30023` with `t=diy`. + `DIY_ACTIONS`); `src/pages/DiyPage.tsx` renders it. **Policy: link to our own + app sections (`to`) where we have content; otherwise show the topic as an + unclickable `comingSoon` card** — no external links. Registered as a nav-catalog + item (id `diy`, Hammer) so it shows in the desktop "More" menu **and** the + mobile burger, and is linked from the **site footer** + the **map links strip**. + Cross-links to `/lab?craft=building` (Builder), `/crews`, `/create-spot`, + `/create-listing`, `/lab?craft=coaching`, `/marketplace`. Next: write our own + step-by-step guides (NIP-23 `30023` with `t=diy`) to flip the coming-soon cards + live, plus the in-app deck cost calculator. - **App Shop** (`/app-shop`, `src/pages/AppShopPage.tsx`): SkateSpots merch, to be paid in **sats only (Lightning or Cashu)** — no cards/accounts — sold **locally, on request**: there is **no cart, no checkout, no shipping**. Buying diff --git a/src/i18n/en.ts b/src/i18n/en.ts index 53749ab..1b01f91 100644 --- a/src/i18n/en.ts +++ b/src/i18n/en.ts @@ -795,7 +795,8 @@ diyUi: { tagline: 'Guides, open tools and plans to build your own decks, ramps and concrete spots — then find the people, places and market to go with them.', doItWithPeople: 'Do it with people', source: 'Source', - footer: 'Resources link to their original authors — we curate, we don’t rehost. Always work safely: pads, gloves and eye protection.', + comingSoon: 'Coming soon', + footer: 'Step-by-step guides are on the way. For now: find the people who build in The Lab, map your spot, and buy or sell in the Marketplace. Work safely — pads, gloves and eye protection.', categories: { boards: 'Boards', ramps: 'Ramps & wooden obstacles', @@ -812,6 +813,7 @@ diyUi: { flatbar: { title: 'Build a flatbar', blurb: 'Cheap, portable and the best way to learn rails.' }, concreteBasics: { title: 'Concrete basics', blurb: 'Mixing, forming and finishing a ledge or bank that lasts.' }, coping: { title: 'Coping & edges', blurb: 'How to set coping and finish a transition for a smooth grind.' }, + buyParts: { title: 'Buy parts & gear', blurb: 'Pick up decks, hardware and tools from sellers in the Marketplace.' }, mapSpot: { title: 'Map your DIY spot', blurb: 'Built something? Add it to the map so others can find and skate it.' }, regrip: { title: 'Regrip a board', blurb: 'Strip old grip and lay new grip cleanly.' }, tune: { title: 'Tune bearings & trucks', blurb: 'Clean bearings, swap bushings and set your truck geometry.' }, diff --git a/src/i18n/es.ts b/src/i18n/es.ts index 7c53473..8163743 100644 --- a/src/i18n/es.ts +++ b/src/i18n/es.ts @@ -795,7 +795,8 @@ diyUi: { tagline: 'Guías, herramientas abiertas y planos para hacer tus propias tablas, rampas y spots de hormigón — y luego encontrar a la gente, los sitios y el mercado.', doItWithPeople: 'Hazlo con gente', source: 'Fuente', - footer: 'Los recursos enlazan a sus autores originales: curamos, no rehospedamos. Trabaja siempre con seguridad: protecciones, guantes y gafas.', + comingSoon: 'Próximamente', + footer: 'Las guías paso a paso están en camino. Por ahora: encuentra a quien construye en The Lab, mapea tu spot y compra o vende en el Marketplace. Trabaja con seguridad: protecciones, guantes y gafas.', categories: { boards: 'Tablas', ramps: 'Rampas y obstáculos de madera', @@ -812,6 +813,7 @@ diyUi: { flatbar: { title: 'Haz un flatbar', blurb: 'Barato, portátil y la mejor forma de aprender a deslizar.' }, concreteBasics: { title: 'Fundamentos del hormigón', blurb: 'Mezcla, encofrado y acabado de un bordillo o bank duradero.' }, coping: { title: 'Coping y bordes', blurb: 'Cómo colocar el coping y rematar una transición para un grind suave.' }, + buyParts: { title: 'Compra piezas y material', blurb: 'Consigue tablas, tornillería y herramientas de vendedores en el Marketplace.' }, mapSpot: { title: 'Mapea tu spot DIY', blurb: '¿Has construido algo? Añádelo al mapa para que otros lo encuentren.' }, regrip: { title: 'Cambia el grip', blurb: 'Quita el grip viejo y coloca el nuevo limpio.' }, tune: { title: 'Ajusta rodamientos y ejes', blurb: 'Limpia rodamientos, cambia gomas y ajusta la geometría de los ejes.' }, diff --git a/src/lib/diyGuides.ts b/src/lib/diyGuides.ts index fea6542..2e299d9 100644 --- a/src/lib/diyGuides.ts +++ b/src/lib/diyGuides.ts @@ -1,12 +1,12 @@ /** * Curated DIY resources — how to make your own boards, ramps and concrete spots. * - * This is a **seed** list (vetted links + in-app actions), not user content, so - * it needs no moderation. Titles/blurbs are i18n keys (`diyUi.*`). To extend, - * just add entries here. + * Policy: point at **our own** app sections whenever we have something relevant + * (`to`), and otherwise show the topic as an unclickable **"coming soon"** card + * (`comingSoon: true`) instead of linking out. So this is a roadmap of what the + * DIY hub will cover, with live links where the app already has content. * - * ⚠️ Link out, never rehost: credit the source. External URLs are rendered - * through `sanitizeUrl` on the page. + * Content, not user data — no moderation. Titles/blurbs are i18n keys (`diyUi.*`). */ export type DiyCategoryId = 'boards' | 'ramps' | 'concrete' | 'repairs' | 'tools'; @@ -17,7 +17,7 @@ export interface DiyCategory { emoji: string; } -/** A resource card — either an external guide (`url`) or an in-app action (`to`). */ +/** A resource card — an in-app link (`to`) or a "coming soon" placeholder. */ export interface DiyCard { id: string; /** Omit for the cross-link actions block. */ @@ -25,10 +25,10 @@ export interface DiyCard { titleKey: string; blurbKey: string; emoji: string; - /** Shown as a credit for external links. */ - source?: string; - url?: string; + /** In-app route. Omit for a coming-soon card. */ to?: string; + /** No destination yet — rendered unclickable with a "Coming soon" badge. */ + comingSoon?: boolean; } export const DIY_CATEGORIES: DiyCategory[] = [ @@ -42,13 +42,12 @@ export const DIY_CATEGORIES: DiyCategory[] = [ export const DIY_CARDS: DiyCard[] = [ // ── Boards ──────────────────────────────────────────────────────────────── { - id: 'oss-build', + id: 'ossBuild', category: 'boards', emoji: '🛹', titleKey: 'diyUi.cards.ossBuild.title', blurbKey: 'diyUi.cards.ossBuild.blurb', - source: 'Open Source Skateboards', - url: 'https://opensourceskateboards.com', + comingSoon: true, }, { id: 'sk8cad', @@ -56,28 +55,25 @@ export const DIY_CARDS: DiyCard[] = [ emoji: '🧊', titleKey: 'diyUi.cards.sk8cad.title', blurbKey: 'diyUi.cards.sk8cad.blurb', - source: 'Open Source Skateboards', - url: 'https://sk8cad.com', + comingSoon: true, }, { - id: 'deck-cost', + id: 'deckCost', category: 'boards', emoji: '💰', titleKey: 'diyUi.cards.deckCost.title', blurbKey: 'diyUi.cards.deckCost.blurb', - source: 'Open Source Skateboards', - url: 'https://opensourceskateboards.com', + comingSoon: true, }, // ── Ramps & wooden obstacles ───────────────────────────────────────────── { - id: 'ledge-box', + id: 'ledgeBox', category: 'ramps', emoji: '📦', titleKey: 'diyUi.cards.ledgeBox.title', blurbKey: 'diyUi.cards.ledgeBox.blurb', - source: 'Instructables', - url: 'https://www.instructables.com/howto/skate+ledge/', + comingSoon: true, }, { id: 'quarterpipe', @@ -85,8 +81,7 @@ export const DIY_CARDS: DiyCard[] = [ emoji: '🌊', titleKey: 'diyUi.cards.quarterpipe.title', blurbKey: 'diyUi.cards.quarterpipe.blurb', - source: 'Instructables', - url: 'https://www.instructables.com/howto/skate+ramp/', + comingSoon: true, }, { id: 'flatbar', @@ -94,19 +89,25 @@ export const DIY_CARDS: DiyCard[] = [ emoji: '➖', titleKey: 'diyUi.cards.flatbar.title', blurbKey: 'diyUi.cards.flatbar.blurb', - source: 'YouTube', - url: 'https://www.youtube.com/results?search_query=how+to+build+a+skate+flatbar', + comingSoon: true, }, // ── Concrete & DIY spots ───────────────────────────────────────────────── { - id: 'concrete-basics', + id: 'mapSpot', + category: 'concrete', + emoji: '📍', + titleKey: 'diyUi.cards.mapSpot.title', + blurbKey: 'diyUi.cards.mapSpot.blurb', + to: '/create-spot', + }, + { + id: 'concreteBasics', category: 'concrete', emoji: '🧱', titleKey: 'diyUi.cards.concreteBasics.title', blurbKey: 'diyUi.cards.concreteBasics.blurb', - source: 'Instructables', - url: 'https://www.instructables.com/howto/concrete+skatepark/', + comingSoon: true, }, { id: 'coping', @@ -114,16 +115,7 @@ export const DIY_CARDS: DiyCard[] = [ emoji: '🛞', titleKey: 'diyUi.cards.coping.title', blurbKey: 'diyUi.cards.coping.blurb', - source: 'YouTube', - url: 'https://www.youtube.com/results?search_query=diy+skatepark+coping', - }, - { - id: 'map-spot', - category: 'concrete', - emoji: '📍', - titleKey: 'diyUi.cards.mapSpot.title', - blurbKey: 'diyUi.cards.mapSpot.blurb', - to: '/create-spot', + comingSoon: true, }, // ── Repairs & tuning ───────────────────────────────────────────────────── @@ -133,8 +125,7 @@ export const DIY_CARDS: DiyCard[] = [ emoji: '🩹', titleKey: 'diyUi.cards.regrip.title', blurbKey: 'diyUi.cards.regrip.blurb', - source: 'YouTube', - url: 'https://www.youtube.com/results?search_query=how+to+regrip+a+skateboard', + comingSoon: true, }, { id: 'tune', @@ -142,33 +133,38 @@ export const DIY_CARDS: DiyCard[] = [ emoji: '🔩', titleKey: 'diyUi.cards.tune.title', blurbKey: 'diyUi.cards.tune.blurb', - source: 'YouTube', - url: 'https://www.youtube.com/results?search_query=clean+skateboard+bearings+bushings', + comingSoon: true, + }, + { + id: 'buyParts', + category: 'repairs', + emoji: '🛒', + titleKey: 'diyUi.cards.buyParts.title', + blurbKey: 'diyUi.cards.buyParts.blurb', + to: '/marketplace', }, // ── Tools & plans ──────────────────────────────────────────────────────── { - id: 'print-molds', + id: 'printMolds', category: 'tools', emoji: '🖨️', titleKey: 'diyUi.cards.printMolds.title', blurbKey: 'diyUi.cards.printMolds.blurb', - source: 'Printables', - url: 'https://www.printables.com/search/models?q=skateboard+mold', + comingSoon: true, }, { - id: 'sk8cad-tools', + id: 'sk8cadTools', category: 'tools', emoji: '📐', titleKey: 'diyUi.cards.sk8cadTools.title', blurbKey: 'diyUi.cards.sk8cadTools.blurb', - source: 'Open Source Skateboards', - url: 'https://sk8cad.com', + comingSoon: true, }, ]; /** - * Cross-links into the rest of the app — the point of the section: turn a guide + * Cross-links into the rest of the app — the point of the section: turn a topic * into a person, a place, or a sale. */ export const DIY_ACTIONS: DiyCard[] = [ diff --git a/src/pages/DiyPage.tsx b/src/pages/DiyPage.tsx index 81550fe..20e9deb 100644 --- a/src/pages/DiyPage.tsx +++ b/src/pages/DiyPage.tsx @@ -1,49 +1,59 @@ import { useSeoMeta } from '@unhead/react'; import { Link } from 'react-router-dom'; -import { Hammer, ExternalLink, ChevronRight } from 'lucide-react'; +import { Hammer, ChevronRight } from 'lucide-react'; import { useTranslation } from '@/contexts/language'; -import { sanitizeUrl } from '@/lib/sanitizeUrl'; import { cn } from '@/lib/utils'; import { DIY_CATEGORIES, DIY_CARDS, DIY_ACTIONS, type DiyCard } from '@/lib/diyGuides'; /** - * DIY — curated resources for making your own boards, ramps and concrete spots, - * with cross-links into the rest of the app (find a builder, map a spot, sell). - * Content lives in `src/lib/diyGuides.ts`. + * DIY — resources for making your own boards, ramps and concrete spots, with + * cross-links into the rest of the app (find a builder, map a spot, sell). + * Content lives in `src/lib/diyGuides.ts`. Cards with no destination yet render + * unclickable with a "Coming soon" badge. */ function DiyCardView({ card }: { card: DiyCard }) { const { t } = useTranslation(); - const external = !!card.url; const body = ( <> {card.emoji} - {t(card.titleKey)} + + {t(card.titleKey)} + {card.comingSoon && ( + + {t('diyUi.comingSoon')} + + )} + {t(card.blurbKey)} - {card.source && ( - {t('diyUi.source')}: {card.source} - )} - {external - ? - : } + {card.to && } ); - const cls = cn( - 'group flex items-start gap-3 rounded-2xl border border-white/10 bg-white/[0.03] p-4 transition-colors', - 'hover:border-[#ccff00]/40 hover:bg-white/[0.06]', - ); + const base = 'flex items-start gap-3 rounded-2xl border border-white/10 p-4 transition-colors'; - if (external) { + if (!card.to) { + // Coming soon — deliberately not a link. return ( - +
{body} - +
); } - return {body}; + + return ( + + {body} + + ); } export default function DiyPage() {