Changelog

Recent changes to quitting7oh.org: new pages, rewrites, design tweaks, and editorial sweeps. Newest entries first.

This page tracks substantive changes to the site: new pages, rewrites, layout work, sourcing passes, editorial cleanups. Newest entries at the top. The same content lives in CHANGELOG.md at the repo root, which is the source this page is generated from.

2026-07-05

Cat’s Claw page rewritten around corynoxine B

  • Cat’s Claw rewritten end-to-end. The earlier version had corynoxine B bolted onto a structure built before it, with two separate botanical-cover passages and a trailing synthetic-chemistry section that read as scattered. New structure leads with what’s actually in the products, makes corynoxine B the spine of the explanation (pharmacology, then why it works as an unscheduled cover ingredient), folds the two botanical-cover passages into one “cover story” section, and ends with clinical risks and a quit/withdrawal wayfinder. Dropped a weak kratomscience.com citation. Same verified facts as the prior pass; clearer sequence.
  • The earlier same-day edit (superseded by the rewrite above) first added corynoxine B, the mu-opioid-active oxindole alkaloid being corynoxine B, the mu-opioid-active oxindole alkaloid being reported in the newer “Cat’s Claw” product lines. New section explains why it works as a regulatory-evasion ingredient: it’s a real kratom/Uncaria alkaloid, it’s opioid-active (mu partial agonist, Ki ≈ 118 nM, per the 2026 Frontiers receptor study already cited on the page), and it is not named in any of the July 2026 DEA scheduling notices, so a corynoxine-B product can sit under the 7-OH threshold and still deliver opioid effects. Cross-linked to The Federal 7-OH Ban.
  • Corrected the “real cat’s claw isn’t psychoactive” framing: the same Frontiers study found mitraphylline and rhynchophylline (the marketing-cover alkaloids) inactive at opioid receptors but corynoxine B active, so the page now draws that distinction instead of implying the whole alkaloid class is inert. Reconciled the clinical-implications and “if you’re already taking one” sections (corynoxine B is natural, not synthetic) and added a wayfinder to the quit/withdrawal pages.

2026-07-04

Leaf-alongside-Suboxone correction

  • Fixed a factual error on Paths Off 7-OH: the “Moving between rungs” list claimed leaf alongside Suboxone is “uncommon and unnecessary; bupe already covers the receptors.” Bupe covers the mu side only; the community commonly recommends a small amount of leaf when minor-alkaloid withdrawal (adrenergic and serotonergic) breaks through. Rewritten to say that, with a link to the minor-alkaloids page.
  • Same list, next line: the naltrexone warning linked /other-tools/low-dose-naltrexone, a path that soft-404s to the homepage shell (the naltrexone pages live under post-acute/). Re-pointed to Naltrexone and added _redirects bridges for the two old naltrexone paths so stale inbound links land on the right pages.

2026-07-03

Federal scheduling action: new page + site-wide banner

  • New page: The Federal 7-OH Ban (/compounds/7-oh-ban) covering DEA’s July 1, 2026 notices of intent to temporarily schedule 7-OH above a 0.05% / 1 mg threshold (Docket DEA-1570) and to place mitragynine pseudoindoxyl, MGM-15, and MGM-16 fully in Schedule I (Docket DEA-1644). Leads with the date question readers actually have (nothing banned yet; Federal Register publication July 6; earliest effective date August 5, 2026, per the 30-day requirement in 21 U.S.C. § 811(h)), then the threshold mechanics, the HHS OASH public-comment window (Docket HHS-OASH-2026-0232, due July 31), what Schedule I means in practice, and a planning section routing to the site’s documented paths off. All dates and quotes verified against the Federal Register full texts and the DEA/HHS press releases.
  • New site-wide banner (SchedulingBanner.tsx, mounted in BaseLayout.astro): one-line announcement linking to the new page on every page. Dismissible, persisted in localStorage under a dated key so a future re-announcement can reset it; hides itself on the ban page.
  • Editorial pass on the ban page after review: broke up the run of same-shape “The X” section headers and cut performative-emphasis phrasing (“Read the 1 mg line again…”, “Practical translation:”, “Here is the clock”) in favor of direct statements.
  • Stale federal-status text updated on the 7-OH, kratom leaf, MGM-15, MGM-16, and pseudo pages (“DEA has not acted as of mid-2026” and similar), each now pointing at the ban page. Compounds category blurb mentions the scheduling action.

2026-06-20

Veterinary gabapentin on the helper-meds page

  • Added a Veterinary gabapentin (no prescription needed) subsection to Helper Medications: vet gabapentin is the same molecule in the same manufacturer packaging and standard strengths, a no-prescription route the community uses. Framed with the existing dosing/taper cautions, the opioid+benzo+alcohol respiratory warning, a “legality varies by state” note, and a pointer back to telehealth as the simpler path. Two verified vendor callouts: Dog & Cat Stuff and Pet Pharm Canada (both confirmed live, in manufacturer packaging, purchasable).

2026-06-19

Brand & style guide

  • New page: /brand — a live, theme-aware brand showcase: the Lift Cup logo and its color mapping, the semantic color tokens, all 8 variants in light and dark, the Fraunces + IBM Plex Sans type system and scale, component specimens (buttons, callouts, cards, inputs, focus rings), shape/surface rules, voice, and links to the downloadable assets. Standalone page on BaseLayout (wide, full container), built from the real Logo, Callout, and buttonVariants so the specimens stay truthful. For anyone building an app or companion tool on the brand.
  • In-page theme switcher. A sticky theme bar (8 color swatches + light/dark/system toggle) and a clickable variant catalog let you recolor the whole page from the page itself, not just the header. Both share the header picker’s storage keys and apply logic and stay in sync via a MutationObserver; the on-dark logo preview recolors to the active variant’s dark palette. New BrandThemeControl island; Logo gained a link={false} option so the on-page specimens aren’t homepage links.
  • New doc: docs/brand/style-guide.md — the written companion (exact HSL/hex tokens, font specs, logo usage), GitHub-linkable, cross-referencing the existing logo SVGs and favicons.
  • AI agent context for downstream builds. A copy-pasteable block on /brand (and docs/brand/agent-context.md) that someone can drop into their own project’s AGENTS.md/CLAUDE.md so an AI agent matches the brand. It links the rendered guide, the repo tokens/logo, and tells the agent to scrape with Playwright if it can’t fetch directly. The page reads the file at build so the two never drift.

2026-06-16

Recovery coaching resource (You Are Accountable)

  • New page: Recovery Coaching in resources (sort: 3). Explains what peer recovery coaching is, what it costs, and how to weigh a paid service, with You Are Accountable as the first listed entry. Follows the telehealth-comparison model: neutral, every claim cited and dated, the company’s own stats labeled as unaudited claims, and a “questions to ask before you sign up” checklist.
  • Holds the no-ads line. The page opens with a disclosure that no money changes hands and that a service appears only because community members can use it, keeping the welcome page’s no-sponsorship promise intact. Free community options (Discord, r/quitting7oh, mutual aid, meetings) are named first, with paid coaching framed as an optional add-on. Scholarships are mentioned softly: limited slots, ask the company directly.
  • Resources category blurb updated to name recovery coaching.

2026-06-09

Typography refresh: IBM Plex Sans + Fraunces

  • Body font is now IBM Plex Sans (variable, self-hosted via Fontsource), replacing Inter. Slightly warmer, better x-height, and holds up in dense tables; the Inter-specific cv feature settings went with it.
  • Content headings are now Fraunces, the display serif that was already shipped but only used in the logo. Applies to article prose headings (H1–H4), page titles, and the sitemap section headings at weight 600. Small UI headings (sidebar labels, calculator panels, crisis dialog) stay on the sans.
  • Picked from a ten-font contact sheet (docs/font-contact-sheet.html) rendered on the site’s own light/dark palettes.

Desktop navigation upgrades

  • Scroll-spy in the right-rail TOC. The “On this page” rail now highlights the section currently in view (left border + foreground text on the active link, aria-current="location" for screen readers). Tracking uses a rAF-throttled scroll listener against the same 5rem header offset the heading anchors use, with a bottom-of-page case so the last section activates even when its heading can’t reach the reading line.
  • Anchor bar for wide pages. Pages with wide: true hide the right-rail TOC and previously offered no in-page navigation. They now get a horizontal H2 anchor bar under the title (TocWide.astro, static markup, no hydration). Currently applies to pharmacology/chemical-structures.
  • Taper calculators go wide. The four taper calculator pages (7-OH, Suboxone, kratom leaf, SR-17 cross-taper) now use the wide layout: the calculator gets the full container width and the right-rail TOC is dropped — there’s little prose on those pages for it to navigate.
  • Click-to-copy heading anchors. The hover # on H2–H4 now copies the section URL to the clipboard (with a “Copied” bubble and a polite screen-reader announcement) instead of jump-navigating. The hash still updates via replaceState, modified clicks keep normal anchor behavior, and browsers without clipboard access fall back to plain navigation. Vanilla delegated listener in DocLayout.astro — no per-heading hydration.
  • Copy the page link from the breadcrumb. The current-page crumb is now a link with a copy icon; clicking it copies the page URL. Same “Copied” feedback and screen-reader announcement as the heading anchors.

Source-anchored audit fixes across the site

Acting on docs/source-audit-2026-06-09.md. Four-pass sweep.

  • Propagation chain. Replaced PMID 15165526 (mis-cited as “Yang et al. 2005” — actually Ulfberg’s editorial on Karl-Axel Ekbom) with Garcia-Borreguero et al., IRLSSG/EURLSSG, Sleep Med 2016 in CLAUDE.md and the five content pages that propagated it: helper-meds.md, start-here/7-oh-withdrawal-help.md, post-acute/impending-doom-anxiety.md, quit-7-oh-with-kratom-leaf.md, mat-suboxone/why-suboxone-isnt-working.md.
  • Pseudoindoxyl Kᵢ corrected. compounds/mitragynine-pseudoindoxyl.md had MP Kᵢ = 0.087 nM and mitragynine Kᵢ = 7.24 nM from a Wikipedia propagation. Replaced with Varadi 2016’s measured value (MP Kᵢ ≈ 0.8 nM) and Obeng 2020’s mitragynine Kᵢ (≈ 160–240 nM).
  • pharmacology/morphine-vs-kratom.md Kᵢ table re-anchored. Removed the fabricated “Kruegel 2019 (hMOR, ~7 nM)” mitragynine citation. Kruegel 2019 reports EC₅₀ 339 nM functional, not Kᵢ. Now cites Obeng 2020 (hMOR Kᵢ ≈ 161 nM) for mitragynine and Obeng 2020 + Matsumoto 2004 for 7-OH. Buprenorphine corrected from “~1 nM, similar to morphine” to “~0.2 nM, tighter than morphine”. MGM-15 dual-receptor causal language reworked with Matsumoto 2014 Kᵢ values. MGM-16 240× framing clarified as “240× oral, ~71× sc”.
  • Citation mis-attributions fixed. suboxone-bernese-method.md: Hess → Menard & Jhawar 2022, Vu → Alexander & Woford 2025, Sandhu → Wong et al. 2021 (NCT04234191). sublocade-brixadi.md: Kazim → Hayes & Mills 2025 (re-described as withdrawal characterization, which is what the paper actually documents). post-acute/7-oh-recovery-timeline.md and dopamine-recovery.md: Volkow → Cosgrove on PMC3760378. start-here/cravings-and-relapse-thoughts.md: Smith → Henningfield on PMC10311168.
  • Frontiers citation removed where the paper doesn’t contain the cited claim. Pseudo-binds-tighter-than-bupe now cites Varadi 2016 (with measured Kᵢ values) on sows-cows-induction-guide.mdx, suboxone-for-7oh.md, and why-suboxone-isnt-working.md. MGM-15 dual mu/delta now cites Matsumoto 2014.
  • Numeric fixes. Sublocade list price $1,500–1,900 → $2,100–2,200 (2024–2026 list per drugs.com / GoodRx). Ohio scheduling date Dec 16 → Dec 12, 2025 on compounds/kratom-leaf.md. Mitragynine α-adrenergic strength “moderate” → “weak (micromolar)” per Obeng 2020 on kratom-leaf.md, kratom-minor-alkaloids.md, 7-oh.md. Leaf 7-OH math fixed (0.04% of 1 g ≈ 0.4 mg, not 0.5–4 mg). CLAUDE.md line count: 700 → 1,000. HIMS: Motivation → Motivational. EVALI 2,800 hospitalizations softened to “around 2,800” per CDC final tallies. Suboxone receptor-occupancy table reconciled to De Aquino values used elsewhere on the site (2 mg = 41%, 16 mg = 80%, 32 mg = 84%, vs the prior overstated row). NIDA chronic-disease comparison: dropped diabetes (NIDA’s published comparison only includes hypertension and asthma).
  • Half-life claims qualified. “7-OH plasma half-life ~100 minutes” on five pages (compounds/7-oh.md, sows-cows-induction-guide.mdx, suboxone-for-7oh.md, suboxone-rapid-taper.md, 7-oh-taper-calculator.mdx) re-labeled as community-observed effect duration with a note that no direct human PK is published (Tanna 2024 reports the 7-OH metabolite at 4–9 hr). The compound page has the long explanation; other pages link to it. MGM-15 “~15 hour half-life” on three pages (sows-cows-induction-guide.mdx, suboxone-for-7oh.md, suboxone-bernese-method.md) re-labeled as “community-reported effective duration roughly 9–15 hours per dose (no published human PK)”. The MGM-15 compound page already had the caveat; sibling pages now match.
  • Smaller items. Kruegel-2019 “prodrug” attribution on kratom-leaf.md rephrased (Kruegel doesn’t use the term). Mitragynine human half-life on quit-7-oh-with-kratom-leaf.md corrected from “24+ hours” to “roughly 7 to 39 hours” per Huestis 2024. Zamboni 2019 over-claim on endocrine-recovery.md corrected (no significant methadone vs buprenorphine difference per published abstract). SAMHSA helpline URL bumped past 301 redirect (samhsa.gov/find-help/national-helpline…/helplines/national-helpline) across five content pages. Bicycle Health BBB profile link removed (URL 404s; rating data kept).
  • Reddit-side date corrections on about/the-community.mdx: subreddit creation August 2024 → July 2024 (Playwright-verified Jul 16, 2024). The May-2026 stepdown framing split into two events: February 2026 Discord step-back (post 1reegp9 is about Discord policy from Feb 25, 2026), May 2026 subreddit step-down (post 1t0u0jo from May 1, 2026).

The audit had one false positive: it claimed quit-7-oh-with-mitragynine.md had swapped Kᵢ values for 7-OH (78 nM) and mitragynine (709 nM). The cited paper (PMC7923387, Obeng 2021 JPET) actually reports those exact values; the page is correct. Skipped.

Calculator callouts on the path master pages

  • Every taper calculator now has a prominent callout on its corresponding path master page, placed right above the first H2 so a reader arriving on the master from search or a referral doesn’t have to know the calculator exists to find it.
  • Added on:
  • Same callout pattern across all five: blockquote with a chart emoji, an intent-matching CTA (“Want a day-by-day schedule…”), one-sentence description of what the calculator builds, and a single link out. Rapid-taper page uses the “doesn’t fit your situation” framing rather than the default “want a schedule” framing, since readers landing on rapid-taper already know they want a schedule and need a way to deviate from the templates.

Full DHM/MIT-A cascade: merge into MGM-15 page, stub the old, sweep the references

  • /compounds/mgm15 rewritten as the canonical page for the compound that’s sold under all three labels (MGM-15, MIT-A, DHM). Folded in the unique content from the old /compounds/mit-a-dhm page: the chemistry of how MGM-15 is made (NaBH₄ reduction of 7-OH) and why “reducing mitragynine” wouldn’t give a clean product; the GC-MS reversion problem that lets vendors publish “non-detect 7-OH” COAs on products containing MGM-15; the regulatory landscape (Florida’s 400 ppm 7-OH gap, Ohio explicitly scheduling dihydro-7-hydroxy mitragynine, Louisiana scheduling both mitragynine and 7-OH); dose patterns (10 mg MGM-15 ≈ 30–40 mg 7-OH); the “harder to come off than 7-OH” community pattern; and a practical “for the reader being sold one of these products” section.
  • /compounds/mit-a-dhm converted to a stub that explains the labels point at MGM-15, names the chemistry confusion the original page perpetuated, and pushes readers to /compounds/mgm15 for everything.
  • Cascade across 27 content files. Replaced [MIT-A](/compounds/mit-a-dhm) and similar patterns where MIT-A was being treated as a distinct compound: dropped from compound lists (MGM-15 covers it), converted standalone links to bare market-label text where the framing was already “products sold as MIT-A”, and pointed any remaining /compounds/mit-a-dhm link at /compounds/mgm15. Manual cleanup of redundant bullets that said “MIT-A/DHM: also long-acting. Similar timeline to MGM-15” (which now reads as a compound being similar to itself). Files touched: most of mat-suboxone/*, start-here/*, compounds/*, for-loved-ones/*, other-tools/*, post-acute/*, and the calculator pages.
  • Removed the dihydro-mitragynine structure from /pharmacology/chemical-structures. The structure was an illustration of a compound that doesn’t appear in characterized commercial products — diagramming it in the synthetic-derivatives row was misleading.
  • Affinity is not activity — new dedicated section on /pharmacology/morphine-vs-kratom placed right before the binding-affinity ranking table. Reframes affinity, activity (full / partial agonist / antagonist, ceiling effects), and exposure as three independent things that combine to drive what a compound does in practice — so a reader sees what the Kᵢ numbers tell them and what they don’t (buprenorphine and morphine have similar µ-affinities but very different ceilings). Replaced the briefer caveat below the table with a pointer to this section.

Pharmacology page reflects DHM/MIT-A relabeling

  • Updated /pharmacology/morphine-vs-kratom after the community converged on the fact that products sold as “DHM” or “MIT-A” have been characterized as MGM-15, not as a distinct dihydro-mitragynine compound. The chemistry of saturating the side-chain C=C bond on mitragynine is real, but that compound doesn’t appear in characterized commercial products — so listing it on a page about what’s actually circulating was misleading.
  • Removed the “Dihydro-mitragynine (DHM / MIT-A)” row from all three tables on the page (compounds compared, structural modifications, µ-opioid affinity ranking). The MGM-15 row now mentions that the same molecule is sold as MIT-A and (mislabeled) DHM. Added a dedicated “A note on DHM and MIT-A” subsection so readers searching for either name land on the clarification.
  • Count updated everywhere: “seven compounds” → “six,” “six related to mitragynine” → “five.” Pattern intro reworked since the table now has only one reduction example. “Where to read next” replaces the standalone MIT-A/DHM link with a pointer to MGM-15 carrying the parenthetical “(which covers what’s sold as MIT-A and DHM).”
  • Downstream pages still need the same pass/compounds/mit-a-dhm, /compounds/mgm15, /pharmacology/chemical-structures, and the ~25 other content files that reference DHM or MIT-A as a distinct compound. Tracking the cascade as a follow-up; this commit is the pharmacology-page anchor.

Virtual SMART Recovery meeting finder at /virtual-smart-meetings-now

  • New shareable landing page at /virtual-smart-meetings-now: a third-party viewer over the public SMART Recovery online meeting list, sorted into the reader’s local timezone. Same four-pane structure as the NA page — Live now, Starting soon, Later today, Tomorrow — and the same filter pattern: program chips (4-Point Recovery dominates with 383; Family & Friends 58; Successful Life Skills 4), audience chips (Adults Welcome 410; LGBTQIA+ 9; Women 7; Military, Veterans & First Responders 7; Teens, Young Adults, BIPOC), language chips, and a free-text search across facilitator
    • host city + host state. Copy button per card.
  • Pathminder behavior, surfaced honestly. SMART routes every meeting join through their own gateway (Pathminder / Pathcheck) which only redirects to the actual Zoom/Meet room during the meeting’s active join window. For live or starting-soon meetings the Join Online button on each card links directly to the Pathminder URL — one click, gateway handles the room. For meetings later today or tomorrow, the link instead goes to the meeting’s page on meetings.smartrecovery.org since the gateway wouldn’t open a room outside the window. A note above the panes explains this so readers aren’t surprised.
  • Framing and trademark respect. The page leads with a callout that quitting7oh.org is not affiliated with SMART Recovery, attributes meeting data to © SMART Recovery, and routes update reports back to SMART’s own meeting search.
  • Data pipeline. A new build script at scripts/build-smart-meetings.mjs scrapes the SMART listing UI with multi-city union coverage (Houston, LA, NYC, Kansas City at 1000-mi radius each) because a single-city search misses meetings hosted outside its radius. Across the four cities: 886 raw row appearances, 462 unique meeting IDs after dedup, 445 verified online meetings after per-meeting detail-page validation (drops 17 that had no Pathminder URL — most were in-person meetings that slipped through the meetingType=1 filter).
  • Triple-check that meetings are actually online. The pipeline filters by SMART’s own meetingType=1 URL parameter, additionally validates that each listing row carries the <i class="fas fa-video"> icon + “Online” text, and finally requires a Pathminder URL on the detail page. Any row that fails all three is dropped.
  • Audience-aware split. SMART’s audience field can encode multiple tags like “BIPOC, Young Adults (18-30)” or include a tag that contains its own comma (Military, Veterans & First Responders). The parser does longest-match against the known set from SMART’s own form dropdown so the tag with the literal comma stays intact.
  • Daily refresh. A new cron at .github/workflows/refresh-smart-meetings.yml runs every morning at 09:30 UTC (just after the NA refresh). Daily not weekly because SMART’s listing exposes each meeting’s next occurrence as a specific UTC timestamp, not a recurring template — weekly would leave “next meeting at 7 PM today” stamps stale for days.
  • Homepage hook updated. The NextMeeting card now points readers at both the NA finder and the SMART finder when no kratom-specific meeting is in session, instead of just NA. No specific meeting is named — the finders are the destinations.
  • Added to the human-facing /sitemap under “Standalone tools”.
  • Filter-chip counts reflect what’s actually visible. Initial build showed the build-time dataset count on each chip (e.g. LGBTIA+ “9”), which was misleading: most meetings aren’t in the ~36-hour viewer window of the four panes, so clicking the chip could yield only 2 visible meetings out of the 9 advertised. Chip counts now reflect the visible set (live + soon + today + tomorrow), so the number on the chip matches what you see when you click it. Tags with no current visible meetings are hidden unless already active (so they don’t disappear under your cursor).

Virtual NA meeting finder at /virtual-na-meetings-now

  • New shareable landing page at /virtual-na-meetings-now: a third-party viewer over the public Narcotics Anonymous® virtual meeting list, US English-language only, sorted into the reader’s local timezone. The page leads with the always-on 24/7 room as a featured card, then four panes: Live now (started in the last hour), Starting soon (next 60 minutes), Later today, and Tomorrow. Each card has a one-click Zoom join with the passcode pre-filled where the host published it (~80% of Zoom rows); the others display the raw passcode for typing.

  • Filter bar across the top: meeting-type chips (Newcomer, Discussion, Speaker, JFT/Basic Text/Step/Literature Studies, Meditation, Topic, Men, Women, LGBTQ+, Young People, Hybrid), an Open/Closed radio, and a free-text search box that matches against group name, city, and state.

  • Framing and trademark respect. The page leads with a callout that quitting7oh.org is not affiliated with Narcotics Anonymous World Services or any NA group. NA® and Narcotics Anonymous® carry the registered-mark symbol on first prominent use. Meeting data is attributed to © Narcotics Anonymous World Services, Inc. The open vs closed distinction is expanded into a two-card definition list with NA’s own wording (“for addicts only”) — readers can see upfront whether a meeting is for them or whether they’re welcome as a curious newcomer or family member. Meeting-update reports are routed back to na.org’s own “Submit Update” form rather than being collected on our end.

  • Data pipeline. A new build script scripts/build-na-meetings.mjs pulls the full week of meetings from na.org’s admin-ajax endpoint (the same one their /meetingsearch/virtual-meeting-search/ page uses), filters to US + English (4,104 of 7,043 raw rows), normalizes into a render-ready shape, and writes src/data/na-meetings.generated.json. The Astro page imports the JSON at build time so the page is fully static — no runtime data fetch, no Pages Functions.

  • Freshness. A new weekly cron at .github/workflows/refresh-na-meetings.yml runs the fetcher every Sunday 09:00 UTC, content-hashes the result (ignoring the fetched_at timestamp so it’s not a no-op commit), commits if changed, and pushes to main. Cloudflare auto-deploys from the push. One bot commit per week at most.

  • Authorization. NAWS senior leadership approved republication with a link back to na.org and a clear unaffiliated disclaimer.

  • Supporting infrastructure. Extracted a generic src/lib/tz.ts with wallClockToUTC, todayInTimezone, addDays, and nextOccurrence helpers that work against any IANA timezone (the existing src/data/meetings.ts was ET-only). The NA dataset spans dozens of timezones, every meeting carries its own. Pre-existing kratom-meeting code untouched — the new lib is additive.

  • Added to the human-facing /sitemap under “Standalone tools”.

  • Homepage hook. The homepage <NextMeeting> card now surfaces the NA finder when the next kratom-specific meeting isn’t in session (status future, i.e. more than 15 minutes away). A small inline callout above the card body says “The kratom-specific meeting below starts later. There’s a virtual NA meeting happening every hour — find one live.” with a link to /virtual-na-meetings-now. No specific NA meeting is named on the homepage — the finder is the destination, and the reader picks. When a kratom meeting is starting soon, live, or just started, the callout doesn’t appear.

  • Intro container. The intro / disclaimer / open-vs-closed section now spans the full page width rather than the prior max-w-3xl reading column, so the disclaimer aligns visually with the featured card and filter bar beneath it.

  • Blank-URL recovery. ~23% of the US English rows came back from na.org with the link field empty and the actual connection info packed into the password field as free text — patterns like “Zoom ID: 669 913 3088 Password: LL130” and “+1 605.313-4221 Access Code: 3074093”. The build script now parses these out: 807 Zoom meetings (with embedded passcode where present) and 93 NA phone meetings (tel: URLs + access codes) were recovered. Total unjoinable rows dropped from 910 to 11. The remaining 11 are na.org data-entry quirks (“Skype Meeting” labeled rows with Zoom URLs in other fields) — they render with a “Connection details unavailable, check na.org” inline note instead of a broken Join button.

  • Phone meetings as a first-class platform. Surfaced as 93 rows with platform=“Phone”, a tel: link, a Phone icon (not the external-link arrow), a formatted phone number in the room field, and an “Access code” label instead of “Passcode” — NA has run phone meetings for decades and this is legitimate recovery infrastructure.

  • Platform filter. A new chip row in the filter bar lists every detected platform with its count. Zoom (3,788), Phone Call (93), and Google Meet (11) are visible by default; the rest sit behind a “Show all” toggle, matching the meeting-type chip pattern (Online meeting 39, GoToMeeting 4, Microsoft Teams 3, Discord 3, FreeConferenceCall 2, Facebook 2, Jitsi 1). The semantics are OR — selecting multiple chips shows meetings on any of them — because a meeting is on one platform, so AND would be empty. Detection upgraded in scripts/build-na-meetings.mjs: GoToMeeting, FreeConferenceCall, Microsoft Teams Live, Discord, Jitsi all now recognized; previously they fell into the “Online meeting” catch-all. The phone-dial-in platform is labeled “Phone Call” everywhere — chip, card body, copy snippet — for unambiguous reading.

  • Copy meeting details. Every meeting card and the 24/7 featured card now have a Copy button that puts a plaintext snippet on the clipboard:

    NA Meeting: In Spirit
    Discussion · Open
    Wednesdays at 7:00 PM (your local time)
    Zoom · Room 669 913 3088 · Passcode LL130
    https://us02web.zoom.us/j/6699133088?pwd=LL130

    Day-of-week framing rather than specific date since meetings recur weekly. Falls back to a textarea + execCommand('copy') in environments without the async clipboard API.

  • Simplified open/closed callout. Replaced the two-card definition list (added one iteration ago) with a single-paragraph inline explanation. The cards were taking up disproportionate vertical space at the top of the page; one tight sentence with bolded labels carries the same information.

SOWS partial-score early exit

  • The SOWS calculator’s partial-score message now short-circuits when the running sum has already crossed the at-home induction floor (17) or threshold (21). Each SOWS item is 0–4 (never subtracts), so a partial sum past the floor means the final score will also be past it; the remaining items can only raise it. Before, any partial state read “Score so far: X. Y items left,” which implied the reader should keep scoring when the right message was “no need to finish.”
  • Partial sum ≥ 21 → “Past the threshold — no need to keep scoring.”
  • Partial sum 17–20 → “Probably in the induction window.”
  • Partial sum < 17 → unchanged “Score so far: X. Y items left.”
  • Result-panel border tone tracks the ready flag (primary tint when ready), so the visual cue matches the copy.

Standalone tools on the human-facing /sitemap

  • The /sitemap page only iterated the docs content collection, so top-level pages in src/pages/ (notably the new /next-kratom-support-meeting landing) weren’t visible to readers scanning by eye. The XML sitemap at /sitemap-index.xml already caught them via @astrojs/sitemap.
  • Adds a curated “Standalone tools” section after the categories that lists hand-picked top-level pages worth surfacing. Total- pages counter in the header updated to include them.

Rolling meetings page at /next-kratom-support-meeting

  • New shareable landing page that opens with a featured “Next up” card (Kratom Anonymous or There Is A Way Out, whichever is the next live or upcoming meeting) and then a 3-day rolling grid of compact cards grouped by day. Each card has a local-time stamp, live countdown, fellowship + format, platform (Zoom / Google Meet), and is itself a click-target to the join URL.
  • Featured card swaps its badge depending on status: “Next up” while the meeting is still future, then “Starting soon” → “Live now” as the clock turns over. Updates on a 30-second tick.
  • New findUpcomingMeetings() helper in src/data/meetings.ts enumerates recurring meeting occurrences within an N-day window; reuses the existing ET→local-time DST math.
  • Page uses BaseLayout directly (no sidebar, no DocLayout) to match the homepage’s stripped framing — the intent is a clean, share- able link target.

Taper calculator follow-ups

  • SR preload defaults to 3 days instead of 1. The 1-day textbook preload is calibrated for pure short-acting 7-OH; most readers coming through the calculator are on synthetics or stacks where the longer runway works better. Calculator page prose updated to match — points back to the SR-17 page for the 1-day textbook version and to push higher (4–5) for harder cases.
  • No more “0 mg × 1” jump-off row. When the SR jump-off is set to 0, the generator now skips the zero-dose final row and lets the last natural taper day be the end before Stop. When jump-off is non-zero (default 25 mg), it still renders its own labelled Jump-off row with the final-dose note.
  • SR taper doses-per-day eases down proportionally. Previously held at preload doses/day (3) until jump-off, producing fractional per-dose math (33 mg, 25 mg, 17 mg). Now drops 3 → 2 → 1 as the total falls so per-dose mg stays in a sensible 25–50 mg range.
  • Misleading “spaced every 6–8 hours” footnote dropped from the SR table. The hour-spacing is a preload convention; during the taper the schedule reduces frequency over time.
  • New “Copy schedule” button on every calculator. Plain-text taper plan + day-by-day, no AI scaffolding — drops straight into a journal, Notes app, email, or message. Lives next to the existing “Copy AI prompt” and “Save as PDF” buttons; each tracks its own “Copied” confirmation.
  • Sort order fixed: the Taper Calculators landing page now precedes the four sub-calculators in the resources section (landing = sort 4, sub-pages = sort 5–8). Previously the landing and the 7-OH calculator both held sort 4 and collided.

Taper calculators: split into four substance-specific pages

The single mega-calculator at /resources/taper-calculator got too busy once the SR-17 cross-taper was added — it’s structurally a two-substance protocol with four sequential phases, not a single- substance percentage taper like the rest. Split into four focused calculators plus a landing page:

  • /resources/7-oh-taper-calculator — 7-OH, MGM-15 / MIT-A / DHM, and pseudoindoxyl in one calculator with a substance picker (they share the percentage-taper math; defaults differ per compound).
  • /resources/suboxone-taper-calculator — buprenorphine taper with the published 5/7/10/14/21-day rapid-taper schedules built in and percentage-math fallback for non-standard start doses.
  • /resources/kratom-leaf-taper-calculator — kratom leaf in grams, defaulting to a 1 g/day jump-off rather than zero.
  • /resources/sr-17-taper-calculator — the SR-17 cross-taper with all four configurable phases (preload, 7-OH cross-taper, hold, SR taper-down), plus the optional allergy-test day. New standalone Sr17CrossTaper.tsx component; was inline in TaperCalculator.tsx.
  • /resources/taper-calculator — landing page, links to the four sub-pages with a short description of each path. Existing URL is preserved so external links still work.

Other changes that came with the split:

  • TaperCalculator accepts a substances prop (filters the dropdown; hides it entirely when only one is passed) and a storageSuffix so each instance has its own localStorage key and can’t overwrite the others.
  • All calculator instances now save inputs to localStorage and reload on next visit. A “Reset form” link at the top clears saved state and restores defaults.
  • “Source compound” framing in the SR-17 calculator replaced with “7-OH (or your kratom synthetic)” throughout — table column, config-panel labels, print PDF, AI prompt. The protocol math applies to MGM-15 / MIT-A / pseudo too; the helper text calls out that synthetics may need a longer preload.

Legacy Discord channel callout

  • quit-7-oh-with-kratom-leaf.md “If leaf isn’t working” section pointed readers at #kratom-leaf, a leftover from when content routed to specific Discord channels by name. Replaced with the standard pattern: post in the Discord or subreddit to talk through options.

2026-06-08

SOWS calculator on the SOWS/COWS induction-guide page

  • New interactive SOWS calculator at the top of mat-suboxone/sows-cows-induction-guide. 16 items, each scored 0–4 by tapping a button. The page sums the total, names the severity bucket, and prints a light-language induction-readiness hint (“Probably too early”, “Getting close, but probably not yet”, “Probably in the induction window”, “Past the threshold — no need to wait longer”, “Severe range”) so a reader inducting solo at home can see where they are without doing the arithmetic.
  • Log line appears once all 16 items are scored: a single pastable string with the score, severity bucket, and current date/time, plus a “Copy to clipboard” button. Re-scoring later updates the timestamp so users can log each observation as the trajectory climbs.
  • Collapsed by default with a callout-style trigger header (“SOWS calculator — Drop down to take your score”, calculator icon, primary-tinted background, primary-colored chevron) so the surrounding prose stays scannable and the calculator reads as the primary action when you want it.
  • Per-button labels (None / A little / Moderate / A lot / Extreme) sit underneath each number column. Variable-width labels would have made the buttons look uneven if placed inside them; the under-button layout keeps the buttons uniform and the labels always-visible without scroll-back to the top legend.
  • Page renamed from .md to .mdx to host the React island. The existing hand-score item list is kept below for offline / printed use; that section’s heading is now “Self-scoring SOWS (by hand)”.

Peptides page title + two body-prose framing leaks

  • other-tools/peptides-for-withdrawal.md title renamed from “Peptides for Opioid Withdrawal” to “Peptides for 7-OH and Kratom-Synthetic Withdrawal”. Title affects the <title> tag, the SERP heading, the breadcrumb, and the sidebar — the previous framing was the wrong scope for this site.
  • about/this-site.md lead paragraph: “for getting off 7-OH, kratom synthetics, and the opioid dependence they produce” → “for getting off 7-OH, MGM-15, and other kratom-derived synthetics”. Site self-description, same reframe as SITE.description.
  • for-loved-ones/rehabilitation-centers.md: “For 7-OH and opioid dependence, detox handles…” → “For 7-OH and kratom-synthetic dependence, detox handles…”. Page is in the for-loved-ones section of this community; the scope hand-off should match.

The rest of the opioid framing in body content stays as-is — most of it is correct technical claims (bupe is an opioid, kratom- synthetic withdrawal is biochemically opioid withdrawal) or deliberate borrowing from OUD literature. Detailed audit in docs/page-descriptions-audit.md Part 3.

Per-page descriptions: SEO + 7-OH/MGM-15/kratom-synthetic framing

  • 48 content pages got tightened meta descriptions per the audit in docs/page-descriptions-audit.md Part 2. Target: 120-160 chars to fit Google’s SERP truncation (many of the originals ran 180-260 and were getting cut off in every result), with the search-query nouns front-loaded.
  • “Opioid withdrawal” / “opioid dependence” framing replaced with “7-OH and kratom-synthetic withdrawal” / “kratom-derived synthetics” on pages where the page is about our scope, not generic OUD. Compound names (MGM-15, MIT-A, DHM, LDN, ULDN, CRAFT, NARR, COWS, SOWS, Bernese) added to descriptions where they’re the actual search query for that page.
  • One typo fix: compounds/7-oh.md description tapereabletaperable.
  • A handful of the proposed descriptions came in slightly over the 160-char target (160-190) where the SEO surface justified the extra terms; flagged in the audit doc for a follow-up tighten if needed.
  • last_updated bumped on every touched file.

Site-wide scope reframe: 7-OH / MGM-15 / kratom-derived synthetics

  • SITE.description rewritten. The site-wide meta description (used in every <meta name="description">, every og:description, and every embed) previously trailed “…and related opioid dependence”, which framed the site as if it also covered general OUD (heroin, fentanyl, prescription opioids). It doesn’t. The new description names MGM-15 explicitly, says “kratom-derived synthetics” instead of “kratom synthetics” (clearer about the semi-synthetic nature), and lists what the site actually delivers: taper plans, MAT options, helper meds, PAWS guides. Front-loads the search-query nouns so the SERP snippet does triage work.
  • og:image:alt / twitter:image:alt updated in BaseLayout.astro to match the new scope (“…recovery information for 7-OH, MGM-15, and kratom-derived synthetics”). The previous “Community recovery information.” was too generic to do any SEO or accessibility work.
  • Recommendation source: docs/page-descriptions-audit.md Part 1.

Helper Medications rewrite: quick-reference table, cluster ordering, slop pass

  • Above-the-fold restructure: page now opens with a single-table “Quick reference” — symptom cluster → medication → typical dose — covering clonidine, gabapentin, baclofen, trazodone, ondansetron, loperamide, PEG/docusate, NSAIDs/acetaminophen, and bupropion. A reader can take that table to a prescriber without reading the rest of the page.
  • Deep-dive sections reordered into clusters: autonomic (clonidine) → GABA/wired (gabapentin, baclofen + muscle relaxants) → sleep (trazodone, doxepin, mirtazapine, hydroxyzine, melatonin) → GI (anti-nausea, loperamide, constipation) → OTC body aches → post- acute (bupropion, SSRIs/SNRIs, buspirone) → the benzo conversation.
  • Clonidine section expanded to name real alternatives in the sympathetic family: lofexidine (existing), guanfacine (longer- acting alpha-2A agonist), and propranolol (beta-blocker, narrower but overlapping coverage). The page previously left clonidine as if it were the only option.
  • Verbiage pass per the stop-slop ruleset: dropped “(the workhorse)” from clonidine’s heading, the “Why prescribers like it / Why prescribers say no / Why they work / When they do get prescribed” Wh-headers (replaced with flat prose or “Trade-offs”), the “Bottom line” performance-signposting header, “deserves its own callout” (mirtazapine), “worth asking” (mirtazapine), “real tools, not extras” (“X is real” tic), “is a real adjunct” (magnesium), “rare but real” (baclofen seizure caveat), “the realistic alternatives” (benzos antithesis ladder), and “The catch:” (bupropion).
  • Discord channel references removed (#helper-meds was named twice). Project rule routes Discord traffic to the server in general, not to named channels.
  • Diphenhydramine warning relocated from a bottom-of-page bullet into the sleep section, where it belongs alongside hydroxyzine’s RLS caveat. Double-period typo fixed. Duplicate Tizanidine bullet at the bottom removed.
  • Frontmatter description comma-splice fixed; last_updated bumped.

OG / Twitter card image with the brand lockup

  • New public/og-image.png (1200×630) carries the Lift Cup mark and quitting7oh.org wordmark in Fraunces 700, set against the stone- light brand background, with a short tagline below. The wordmark is rendered as genuine Fraunces — vendored Fraunces and Inter TTFs under scripts/og-fonts/ give the rasterizer real glyph data, so embeds don’t fall back to Georgia.
  • BaseLayout <head> adds og:image, the og:image:width/height/ type/alt quartet, twitter:image, and bumps twitter:card from summary to summary_large_image. Replaces the earlier “intentionally no og:image” choice now that the brand is in place.
  • New scripts/build-og-image.mjs (npm run build:og) rebuilds the image from inline SVG using @resvg/resvg-js. Re-run when the brand design changes.

Brand: Lift Cup logo + per-theme favicon system

  • New <Logo> component at src/components/Logo.astro renders the Lift Cup mark plus the quitting7oh.org wordmark as an inline SVG so the strokes inherit theme variables. Cup uses hsl(var(--foreground)), arrow uses hsl(var(--primary)), the 7 uses hsl(var(--primary)), the .org suffix uses hsl(var(--muted-foreground)). One component covers all 16 theme + light/dark states; no logo hex anywhere.
  • Header dot replaced with the lockup. The previous header brand was a 2.5px primary-colored dot followed by plain text; it’s gone. The footer’s brand column header was plain text too; it now uses the same Logo at a smaller size for visual consistency.
  • Footer converted from React to Astro as part of the swap. The component had no interactivity, so dropping client:idle also skips a hydration pass.
  • Fraunces (variable) added via @fontsource-variable/fraunces for the wordmark, alongside Inter. Self-hosted, no Google Fonts. New --font-display token in global.css.
  • Favicons reorganized under public/favicons/<theme>/ with one folder per theme (accent-teal, zinc, slate, stone, neutral, rose, blue, green). Each carries favicon.svg, favicon.ico, apple-touch-icon.png, icon-192.png, icon-512.png, icon-maskable-512.png, and site.webmanifest. The old single-color public/favicon.svg was removed.
  • BaseLayout head now references the default-theme (stone) versions of the SVG favicon, ICO, apple-touch-icon, manifest, and a theme-color meta starting at stone-light’s primary (#604020). The old hardcoded #0d9488 is gone.
  • theme-sync.js runs after the inline ThemeScript and repoints the SVG favicon and theme-color meta whenever data-theme or the .dark class changes. Fixed the script’s default fallback to stone (was accent-teal), since the project’s default omits the data-theme attribute entirely.
  • Reference assets moved out of public/ into docs/brand/: THEME-ICONS-README.md, theme-coverage.html, and the standalone logo SVGs. Nothing on the live site renders those; they’re for design reference and shouldn’t ship as public URLs.

2026-06-07

Taper Calculator: 7-OH stays ≥ 2×/day, tooltip refinements

  • 7-OH keeps at least 2 daily doses throughout the taper. 7-OH’s short half-life (community-reported ~3–5 hours) means dropping to once-daily mid-taper creates long inter-dose withdrawal valleys. The calculator now floors doses-per-day at 2 for 7-OH whenever the reader started at 2 or more times daily. Other substances unchanged (configurable per substance via SubstanceConfig’s minDosesPerDay).
  • Absolute-zero stop day renders as “Stop. Taper complete.” Picking jump-off = 0 appends a final 0-dose day. The previous render showed it as “0 mg × 1/day = 0 mg/day” — and with the new 7-OH 2× floor, it also fired a misleading “Drop dosing to 1×/day starting Day N” callout. Replaced with a single green “Stop. Taper complete.” row. Same fix applied to the printable PDF (green-tinted stop row) and the AI prompt (“Day N: stop (taper complete)”).
  • Per-dose hint uses hover on desktop, tap on mobile. The earlier swap to Popover for mobile support lost the desktop hover affordance — clicks felt wrong for a quick hint. Now detects (hover: hover) and (pointer: fine) and renders shadcn Tooltip on hover-capable devices, shadcn Popover on touch. Same ❓ icon and body content in both modes.
  • Tablet tooltip shows actual mg, not just count. Closest- quarter rounding was misleading: for a 94.5 mg target on a 50 mg tablet, “2 tablets” implies 100 mg, not 94.5. When the dose doesn’t snap cleanly to a quarter, the tooltip now shows both adjacent quarter-tablet options with the mg each delivers — e.g. “1¾ tablets = 87.5 mg or 2 tablets = 100 mg (50 mg per tablet)”. Reader picks whether to under- or over-shoot. Fractional counts ≤ 1 read singular (“¼ tablet”), > 1 plural.
  • Schedule table grows vertically instead of capping at max-h-80 with internal scroll. A 30-day or 90-day taper now expands in line with page scroll instead of trapping the reader in a nested scroll context.

2026-06-06

Taper Calculator bug fixes: schedule length, mobile tooltips, fraction reduction

  • N-day taper now has exactly N rows. The “1 month” preset was producing 32-day schedules, “2 months” 62, “3 months” 92 — an off-by-one caused by the iterative percentage loop pushing one extra row when floating-point rounding put the final dose slightly above the jump-off. Replaced the iterative loop with the closed-form start · ratio^(k/(N−1)) so the count is exact. Convention matches the bupe established schedules: day 1 is the starting dose, day N is the jump-off, N − 1 cuts in between. Custom-mode percentage display and the reverse percentage-→days calculation use the same (N − 1) convention.
  • Per-dose tooltips work on mobile. The bupe strip-equivalents and tablet-count hovers were built on shadcn Tooltip (Radix UI), which is hover/focus-only and doesn’t fire on touch. Swapped both for shadcn Popover — opens on tap (mobile) or click (desktop), closes on outside tap. Same content, same trigger affordance (the ❓ icon next to each per-dose value).
  • Bupe strip fractions are reduced. 4/16 reads as 1/4, 6/16 as 3/8, 8/16 as 1/2. 16/16 reads as “a full N mg strip”; clean multiples read as “N strips of M mg”; mixed values read as “1 1/2 strips of 4 mg” for cases like 6 mg on a 4 mg strip.

Taper Calculator: per-dose × times-per-day model, days everywhere, duration-driven custom mode

Reworked the taper calculator after first-round feedback:

  • Dose input split into per-dose × times-per-day, with a live “Total daily” display. Schedule output now shows per-dose, times-per-day, and total daily on each row. As the total descends, the calculator drops doses-per-day proportionally (ceil(N0 × T / T0)) so per-dose stays in a tolerable range instead of grinding down to fractions of a tablet.

  • Step unit is now days for every substance. The previous weekly math produced 30-week schedules for 20 mg/day dependencies, which doesn’t match how anyone in this community actually tapers. If a reader wants a multi-week taper, they enter the duration in days (14, 21, 60, etc.).

  • Duration presets of 5, 10, 14, and 21 days, plus a Custom duration option. The values line up with the columns on the Suboxone Rapid Taper page so the bupe established schedules fire when the start dose matches. For other substances or non-matching bupe doses, the per-day percentage is derived from the duration: pct = 1 − (jumpOff / totalStart)^(1/days). The preset labels show only the day count (no “easier” or “harder” wording) so the calculator doesn’t editorialize on which duration is right.

  • Custom mode now has bidirectional duration ↔ percentage inputs. Editing days updates the displayed %; editing the % updates the duration. The duration is the source of truth for the math.

  • Per-dose values round to the nearest 0.25 throughout the practical range so no day asks for a hard-to-measure dose like 13.847 mg or 0.996 mg. Sub-0.25 doses (the bupe volumetric tail 0.1 / 0.05 / 0.02 mg) preserve precision via the finer roundDose ladder. Total daily is recomputed from the rounded per-dose × N so the numbers actually multiply out — and uses the same 0.25 grid as per-dose, so 11.75 × 3 reads as 35.25 instead of being rounded to 35.3 by the 0.1-grid branch.

  • Copy AI prompt button copies a self-contained ChatGPT / Claude prompt to the clipboard. The prompt embeds the reader’s plan (substance, doses, schedule, total medication) and asks the LLM to help personalize it by asking the reader about their context (history, polysubstance use, support, etc.). Explicit caveats included: community-derived, not clinical, flag anything dangerous.

  • Save as PDF opens a self-contained printable view in a popup window — separate from the site’s layout chrome (header, sidebar, footer, theme picker, crisis button) — and auto- triggers the print dialog. The popup carries its own minimal styles tuned for paper (system font, light grey accents, page- break-avoiding rows, half-inch margins). Reader picks “Save as PDF” as the destination. The popup closes itself after the print dialog is dismissed. If popups are blocked, the calculator falls back to printing the current page with its print:hidden Tailwind classes — not as clean but still works.

  • Bupe per-dose tooltip: each bupe per-dose value in the schedule table shows a small ❓ icon next to the dose. Hovering (or tapping on mobile) opens a tooltip listing which /16-strip pieces the dose equals across all three commercial Suboxone strip sizes (8 / 4 / 2 mg). Math validates: a 1/16 piece is 0.5 mg from an 8 mg strip, 0.25 mg from a 4 mg strip, 0.125 mg from a 2 mg strip. Doses that don’t snap to clean /16ths get a “volumetric dosing recommended” hint instead. The ❓ icon is hidden in print.

  • Dose-count transitions are called out loudly in the schedule table. When the calculator drops doses-per-day (e.g. 4×/day → 3×/day), an amber-bordered banner row above the transition reads ”↓ Drop dosing to N×/day starting Day X” and the times-per-day cell on that row is bold.

  • Page intro stripped. The calculator is the first thing on /resources/taper-calculator now; the explanatory prose moved below it. The in-form substance notes already cover the substance-specific framing the intro was repeating.

  • Default substance is 7-OH, not bupe. The audience landing on quitting7oh.org is overwhelmingly there for 7-OH; bupe is a later-funnel concern. Dropdown order matches: 7-OH first, then bupe.

  • Duration presets are now substance-aware. Bupe keeps the 5 / 10 / 14 / 21 day presets that line up with the published Suboxone Rapid Taper columns. Everything else (7-OH, MGM-15 / MIT-A / DHM, pseudo, leaf, SR-17 custom) starts at 21 days and stretches into months: 21 days · 1 month · 2 months · 3 months. Backend math still operates in days (pct = 1 − (jumpOff / totalStart)^(1/days)); the labels read in months for the longer presets because that’s how readers think about a taper that runs that long.

  • Jump-off can be 0. Setting the jump-off to 0 was previously rejected because multiplicative % math can’t reach zero in finite steps and the schedule came out empty. Fixed by running the percentage curve to a substance-aware floor (0.02 mg for bupe — the smallest documented volumetric tail value; 2% of the starting total or 0.5 units, whichever is larger, for other substances) and then appending a single 0-dose day as the explicit “taper-all-the-way-off” step. The chart and table both extend cleanly to zero.

  • SR-17 has its own duration presets. The community-validated SR-17 course range is 5 to 14 days, much shorter than the 21-day-to-three-month range that fits 7-OH, MGM-15, pseudo, and leaf. SR-17 now shows 5 days · 10 days · 14 days · Custom. The earlier auto-emitted “100 → 75 → 50 → 25 → jump” community pattern is gone; SR-17 now runs the same percentage math as the rest, scaled to the reader’s chosen duration.

  • Tablet / capsule size input for non-bupe substances. The field starts blank; the reader optionally fills in the size of each tablet, capsule, or dose unit they actually have. A placeholder shows the typical value (7-OH 15 mg, MGM-15 / MIT-A 10 mg, pseudo 5 mg, kratom capsule 0.5 g, SR-17 25 mg) without pre-filling. When a size is set, each per-dose value in the schedule table shows a ❓ icon; hovering reveals the equivalent in tablets / capsules rounded to the nearest quarter (e.g. 1¼ tablets (15 mg per tablet)). Mirrors the bupe strip-equivalents tooltip already on bupe rows. The form’s caveat names that real tablets vary in content between products and batches. Capsules and powder open and can be poured out, so quarter precision applies to both.

  • 7-OH (concentrated)7-OH in the substance dropdown. The (concentrated) parenthetical was redundant on a site whose entire audience is here for the concentrated synthetic; it just added visual noise to the most-picked option.

  • Substance-aware default duration. 7-OH, MGM-15 / MIT-A, pseudo, and leaf now default to 1 month (30 days) instead of 2 months. Bupe still defaults to 14 days (the most-used Suboxone Rapid Taper column); SR-17 defaults to 10 days (middle of its 5–14 day range). Switching substances resets duration to the new substance’s default, matching how per-dose, times-per-day, jump-off, and tablet size already reset.

New page: Taper Calculator

New page at /resources/taper-calculator with a unified taper calculator covering buprenorphine, 7-OH, MGM-15 / MIT-A / DHM products, mitragynine pseudoindoxyl, kratom leaf, and SR-17. Reader enters the current daily dose, the jump-off dose they want to land on, and a taper speed; the calculator emits a schedule chart (Recharts via shadcn), a day-by-day or week-by-week table, total medication required, and a substance-specific note linking to the relevant compound / protocol pages.

Math model:

  • Four difficulty levels on one axis — Easier (5%/week), Clinician recommended (10%/week, CDC default), Harder (20%/week), Super Hard Mode (50% per step) — plus a “Custom” option where the reader enters their own percentage.
  • For buprenorphine, the calculator pulls from the established short-taper schedules on Suboxone Rapid Taper when the starting dose matches a published row (2, 4, 6, or 8 mg) and the chosen speed maps to a published length. For non-matching combinations, it falls back to percentage math. Setting a jump-off below 0.25 mg extends the tail with the page’s published volumetric sub-0.25 mg doses (0.1 → 0.05 → 0.02 mg).
  • For SR-17, picking a named speed emits the community 4-day descending pattern (100 → 75 → 50 → 25 → jump) scaled to the reader’s actual maintenance dose. Custom percentage available for non-standard courses.
  • For everything else, weekly percentage math at the chosen speed.

Form follows site theme tokens — works in all 8 color variants and both light and dark mode. shadcn chart, select, label, and card components added on first use; recharts brought in as a dependency.

/resources/ category blurb updated to mention the calculator alongside the existing entries.

Community page: custom Discord widget replaces the iframe

Swapped the iframe-based Discord embed on The Community for a custom widget (DiscordCard.tsx) that pulls the same live data (server name, online count, member avatars, status dots) directly from discord.com/api/guilds/{id}/widget.json and renders it as a styled card using the site’s theme tokens (bg-card, text-foreground, text-primary, border-border). Followups:

  • Theme variants now match. The site has 8 color variants on top of light/dark/system; the iframe only honored theme=dark|light, so on every non-default variant the embed felt like a foreign object dropped on the page. The custom card inherits whichever variant the reader picked.
  • No Discord JS / iframe sandbox. One JSON fetch on idle; renders nothing while loading, falls back to a small “Join the Discord →” link if Discord rate-limits or is unreachable.
  • Same features: server name, live online count with a pulsing green dot, scrollable member list with avatars and status dots (online green / idle amber / dnd rose), full-width Join button. Channel list and per-member game activity dropped to keep the widget clean.
  • The community page converted from .md to .mdx so it can import the React component. URL unchanged.

Followup: the first render of the widget leaked prose-recovery typography styles (margins on img, bullets and padding on ul/li) into the component, blowing up the spacing and pushing status dots out of position. Fixed by adding not-prose to the component’s outermost div plus explicit m-0 / list-none / block overrides on the avatar and list elements.

Default theme variant: zinc → stone

Switched the default theme variant from zinc (the cool grey monochrome) to stone (the warm neutral). The site now opens in stone for any visitor without a theme-variant localStorage entry. Existing readers who explicitly picked a variant are unaffected.

What changed:

  • The bare :root { … } and .dark { … } blocks now share their declarations with [data-theme='stone']. Zinc moved to a scoped [data-theme='zinc']-only block.
  • ThemeScript.astro and ThemePicker.tsx defaults swapped from 'zinc' to 'stone'. The “no localStorage entry = the default” convention is preserved (picking stone removes the storage key; picking anything else writes it).
  • The zinc-only prose-link tint from the previous entry still fires when the reader explicitly picks zinc.

The zinc theme variant is monochrome by design: --foreground is 240 10% 8% and --primary is 240 8% 18%, both desaturated and only a hair apart in lightness. Prose links inherit text-decoration-color: var(--primary) and so were rendering the same shade as body text — essentially invisible as links. Added a zinc-only override that gives prose anchors (excluding the # heading anchors) a muted-blue tint (hsl(220 55% 38%) light, hsl(220 70% 72%) dark). The rest of the zinc palette (buttons, sidebar primary, anything else using --primary) is unchanged — the zinc aesthetic stays monochrome where it should.

Discord live presence: homepage online-count badge + community page widget embed

The Discord card on the homepage now shows a live “N online” badge next to the “Discord” label, with a small pulsing green dot. Implemented as a small React island (src/components/DiscordOnlineCount.tsx) hydrated client:idle, fetching discord.com/api/guilds/{id}/widget.json from the client. Renders nothing on fetch failure (rate limit, offline, widget disabled) so the static card never shows an error. The “you’re not alone, N people are here right now” signal at the moment of need was the rationale.

The full Discord widget iframe is now embedded on The Community under the Discord section, so visitors can see the server membership preview, the live online count, and the “Join Server” button without leaving the page. 350×500 iframe with max-width: 100% so it shrinks on narrow screens, loading="lazy" so it doesn’t block initial paint, and the same sandbox attributes Discord recommends.

2026-06-05

Rapid taper: total-bupe-required per schedule + every schedule lands at 0.25 mg

Each of the five taper-schedule tables on Suboxone Rapid Taper (2 mg, 4 mg, 6 mg, 8 mg, and the bottom-of-the-taper tail) now has a “Total bupe” row so the reader can see at a glance how much medication the taper calls for. Math verified independently for every schedule.

Same pass surfaced an inconsistency: the prose said “all schedules end at 0.25 mg” but five schedules ended at 0.5 mg. Fixed:

  • 6 mg / 5-day: day 5 changed 0.5 → 0.25 (total 13.25 mg)
  • 6 mg / 7-day: day 7 changed 0.5 → 0.25 (total 22.25 mg)
  • 8 mg / 5-day: day 5 changed 0.5 → 0.25 (total 17.75 mg)
  • 8 mg / 7-day: day 7 changed 0.5 → 0.25 (total 29.25 mg)
  • 8 mg / 10-day: previously a mislabeled 8-day schedule ending at 0.5 mg. Rebuilt to actually run 10 days, top-loaded like the 14-day: 8, 8, 6, 5, 4, 3, 2, 1, 0.5, 0.25 (total 37.75 mg).

The final-day 1 → 0.25 step on the squeezed 5- and 7-day schedules is steep; the bottom-of-the-taper tail (0.1 → 0.05 → 0.02) is the soft-landing tool for readers who find it sharp.

Suboxone page title shortened so the sidebar highlight fits

“Suboxone (Buprenorphine/Naloxone)” was wrapping to two lines in the sidebar; the active-page highlight didn’t fit the second line cleanly. Shortened the title to “Suboxone” so it sits on one line like its siblings. Added “Suboxone is the brand name for buprenorphine/naloxone” inline in the opening sentence so new readers still get the disambiguation.

2026-06-04

MIT-A / DHM page rewrite + MGM-15 chemistry corrections

The MIT-A / DHM compound page (currently at /compounds/mit-a-dihydromitragynine) was wrong on the underlying chemistry. It framed “DHM” as 1,2-dihydromitragynine (a reduction of mitragynine itself) and as a distinct compound from MGM-15. The forensic-chemistry literature (CFSRE monograph, UNODC substance detail, Matsumoto 2014) is consistent: DHM is the same compound as MGM-15 — dihydro-7-hydroxymitragynine, a reduction product of 7-OH, not of mitragynine. The page has been rewritten end-to-end to correct this and to document what’s actually in products sold under those labels.

Eight beats: TL;DR with the correction up front, community reports (effect comparisons, dose patterns, withdrawal severity, inter-product and batch variability, COA references, geographic concentration), the chemistry (selective NaBH₄ reduction of 7-OH gives MGM-15; selective reduction of mitragynine doesn’t give a clean product), how standard GC-MS testing thermally reverts MGM-15 to mitragynine and misses it, the regulatory landscape (Florida 400-ppm 7-OH threshold; Louisiana; Ohio explicitly naming dihydro-7-hydroxy mitragynine in December 2025), marketing patterns, open questions and limits, and what this means for a reader being sold one of these products.

Sourcing combined Playwright-driven Reddit research (~50 substantive threads across r/quitting7oh, r/Kratom_7OH, r/Quittingfeelfree, r/quittingkratom, r/Life_After_7oh, r/7ohbuddies, r/recoverywithoutAA, and several smaller subs) for the empirical side, and peer-reviewed chemistry + the CFSRE forensic-chemistry monograph for the technical and analytical side. Community reports independently confirm the GC-MS reversion pattern, the geographic concentration in 7-OH ban states, and the “marketed as MIT but feels like 7-OH” effect-vs-label dispute that the chemistry hypothesis predicts.

Same commit also corrected four factual errors on the MGM-15 page that the chemistry-verification agent caught against Matsumoto et al. 2014:

  • MGM-16 fluorine position: noted as 10-fluoro per natural-product numbering with the 9-fluoro IUPAC convention referenced (previously only 9-fluoro)
  • MGM-15 receptor Ki: corrected to ~6.4 nM MOR and ~16 nM DOR (previously listed as ~28 nM and ~59 nM with no source)
  • 240×-morphine potency: attributed to MGM-16 only (previously implicitly attributed to MGM-15 in places)
  • 15-hour half-life claim: removed (no traceable primary source; community-reported 9–15 hour duration noted as anecdotal until human PK is published)

Also: the Why Suboxone Might Not Be Working MIT-A subsection updated to reflect that “MIT-A or DHM” products contain MGM-15 plus mitragynine, with induction guidance pointing at the MGM-15 page.

Slug rename executed: the page moved from /compounds/mit-a-dihydromitragynine to /compounds/mit-a-dhm. The old slug encoded the wrong chemistry into the URL (since DHM is dihydro-7-hydroxymitragynine, not dihydromitragynine). The new slug matches what users actually search for. 301 redirects added for both no-trailing-slash and trailing-slash variants of the old slug; the previous Batch 2 redirect (which pointed /mit-a-dhm at the wrong-chemistry slug) was reversed. Internal cross-references swept; check-redirects.sh pair updated.

Follow-up correction: the Marketing section’s MIT-A bullet originally guessed at what “-A” stands for. Vendors actually market it as “Advanced Alkaloids” (wellness-style branding that papers over the actual composition). Corrected to name the marketing claim accurately and note that the unnamed alkaloid content includes MGM-15 in the products that have been tested.

Community routing: only our resources for calls-to-action

New CLAUDE.md rule: when telling readers where to go for community support, name only the Discord and r/quitting7oh. Other subs can be named accurately in sourcing context, but ours go first in that list. The line between routing (only ours) and sourcing (others OK, ours first) is the distinction the rule turns on.

Audit pass identified two existing violations and fixed both:

  • The reach-out ladder on Thinking About Using? listed r/quittingkratom alongside r/quitting7oh as a routing destination. r/quittingkratom removed; routing now goes to Discord + r/quitting7oh only.
  • The “Community support” item on Tapering Off 7-OH led with r/quittingkratom, then r/quitting7oh and the Discord, in a routing voice. Rewritten to route to Discord + r/quitting7oh only.

The mitragynine page itself was rebuilt to follow the rule in both routing and sourcing contexts (Discord + r/quitting7oh as the only routing destinations; r/quitting7oh first in the two sourcing lists that name other subs).

Mitragynine page restructure: lead with the playbook; drop leaf-bridge bullet

The new page restructured so the practical “how this path works” content lands first. The “Three step-down paths” orientation section dropped (the TL;DR already routes to alternates inline). The “Bringing in a clinician” section’s closing community-routing paragraph rewritten to point only at our resources. “Closing” section removed (restating the takeaway is slop).

The “Bridge doses” section in “The path in practice” had a kratom-leaf-powder bullet that didn’t belong on a page scoped to concentrated mitragynine. Plain-leaf use lives on its own page (Quit 7-OH with Kratom Leaf); the mitragynine page now lists two on-topic categories: mitragynine-dominant extract tablets and shots, and “enhanced” kratom (leaf concentrated to ~10% mitragynine). The dose-equivalence paragraph rewritten around the extract dose ranges in the corpus, since the leaf-based equivalence was the only specific dose ratio the community articulates and it’s not this page’s substance.

New page: Quit 7-OH with Concentrated Mitragynine

New page at /other-tools/quit-7-oh-with-mitragynine covering the mitragynine-extract step-down as a documented community path off concentrated 7-OH. The page sits alongside Quit 7-OH with Kratom Leaf in the “Bridges off the synthetics” sidebar group.

Sourcing was unusual for the site: clinical literature on this specific substitution doesn’t exist, so the page is built on primary-source community research (Playwright-driven Reddit scraping across r/Quittingfeelfree, r/quittingkratom, r/Life_After_7oh, r/Kratom_7OH, r/7ohbuddies, and adjacent partial-mu-agonist recovery subs for methodology cross-check) plus peer-reviewed mitragynine and 7-OH pharmacology (Kruegel 2016, Obeng 2021, Hill 2022, Huestis 2024, Singh 2014, Berthold 2022). Eight beats: how this differs from the other taper paths, the receptor-profile logic, what community reports describe (dose ranges, stabilization, taper structure, total duration, outcomes, predictors), risks specific to this path with the contamination concern foregrounded, sourcing in categories with no brand or vendor names, comparison to the other paths, clinician handoff, and an honest closing. The page explicitly surfaces the counter-position from r/Life_After_7oh that substitution paths aren’t legitimate, alongside the r/Quittingfeelfree and r/7ohbuddies endorsements, without picking a side.

SEO-focused slug renames: tapering-with-* → quit-7-oh-with-*

The two bridge pages renamed to lead with the search behavior the audience actually types (“quit 7-oh with kratom leaf”) instead of the internal site framing (“tapering with leaf”). The bridge IS the quit strategy; the taper of the bridge is the second half.

OldNew
/other-tools/tapering-with-kratom-leaf/other-tools/quit-7-oh-with-kratom-leaf

The mitragynine page is brand new and ships at the new slug directly. 301 redirects added for both no-trailing-slash and trailing-slash variants of the leaf-taper old URL. The pre-Batch-1 /other-tools/tapering-with-leaf redirect updated to point at the new slug directly (one hop instead of two). Titles updated to match the new slug pattern: “Quit 7-OH with Kratom Leaf” and “Quit 7-OH with Concentrated Mitragynine”. check-redirects.sh pair list extended; the leaf-rename ships at 26 total verified pairs (52 with trailing-slash variants).

SEO slug renames (Batch 2)

Fifteen more slug renames from docs/seo-suggestions.md Batch 2: the twelve medium-risk renames in the “Recommended renames” table plus three judgment-call renames. Same workflow as Batch 1: 301 redirects added to public/_redirects with trailing-slash destinations, internal-link sweep across content, components, pages, and src/lib/categories.ts.

OldNew
/post-acute/what-is-paws/post-acute/paws-post-acute-withdrawal
/post-acute/kindling/post-acute/kindling-and-relapse
/post-acute/long-term-outlook/post-acute/7-oh-recovery-timeline
/post-acute/impending-doom/post-acute/impending-doom-anxiety
/start-here/thinking-about-using/start-here/cravings-and-relapse-thoughts
/compounds/pseudo/compounds/mitragynine-pseudoindoxyl
/compounds/mit-a-dhm/compounds/mit-a-dihydromitragynine
/pharmacology/minor-alkaloids/pharmacology/kratom-minor-alkaloids
/resources/telehealth/resources/telehealth-for-suboxone
/mat-suboxone/suboxone-cows/mat-suboxone/sows-cows-induction-guide
/mat-suboxone/suboxone-isnt-working/mat-suboxone/why-suboxone-isnt-working
/mat-suboxone/suboxone-risks/mat-suboxone/long-term-suboxone-risks
/about/community/about/the-community
/for-you/start-here/for-you/welcome
/for-loved-ones/start-here/for-loved-ones/welcome

The three judgment-call renames: /about/communitythe-community matches the page title; the two start-here slugs in /for-you/ and /for-loved-ones/ were colliding conceptually with /start-here/ as a category, and renaming both to welcome resolves that ambiguity for crawlers while staying consistent with /start-here/welcome. The QuickMD redirect destination updated alongside the telehealth rename so it lands on the new URL in one hop. scripts/check-redirects.sh extended to cover all 25 Batch 1+2 pairs.

SEO slug renames (Batch 1)

Ten slug renames from docs/seo-suggestions.md Batch 1, all low risk and high search impact. 301 redirects added to public/_redirects for each so existing inbound links keep working; internal-link sweep across content, components, pages, and src/lib/categories.ts so the site itself never hits a redirect.

OldNew
/other-tools/helper-meds-info/other-tools/helper-meds
/other-tools/mega-vit-c-info/other-tools/mega-dose-vitamin-c
/other-tools/quitkit-info/other-tools/quit-kit
/other-tools/sr17018-info/other-tools/sr-17
/other-tools/peptides-info/other-tools/peptides-for-withdrawal
/mat-suboxone/suboxone-info/mat-suboxone/suboxone-for-7oh
/mat-suboxone/sublocade-brixadi-info/mat-suboxone/sublocade-brixadi
/other-tools/tapering-with-leaf/other-tools/tapering-with-kratom-leaf
/start-here/withdrawal-help/start-here/7-oh-withdrawal-help
/start-here/paths-off/start-here/how-to-quit-7-oh

The -info suffix that appeared on six pages was internal-doc shorthand from the retired Discord-export pipeline; dropping it matches what readers search for. The remaining four added missing primary keywords (7-OH, kratom, etc.). All ten files keep their content unchanged; only the URL slug + the internal cross-link graph + categories.ts PINNED_PAGES / CATEGORY_GROUPS entries moved.

Page work

  • Suboxone Rapid Taper picked up a “Bottom of the taper” section with a three-day volumetric tail extension (0.1 → 0.05 → 0.02 mg, explicit mix instructions for each); a note that some readers go down to around 0.018 mg/day before jumping; Sublocade/Brixadi as the escape route if the rapid taper still isn’t working. The 8 mg starting-dose section gained 14- and 21-day extended schedules behind a “playing with fire” warning. The 8 mg section’s two tables and two warnings consolidated into one combined 5/7/10/14/21-day table with a single warning covering both “this is a lot” and the trade-off of extending. The schedule tables (2/4/6/8 mg) are now native <details> disclosures, default- closed, with styled Tailwind summaries; the page is no longer a wall of stacked tables. A callout-reduction pass cut the page from 7 callouts to 3: three stacked top-of-page warnings collapsed into two inline intro paragraphs; the synthetic-users warning was rewritten more accurately (the schedules aren’t uniformly wrong; induction timing and bupe coverage are what differ) and routes to /mat-suboxone/suboxone-isnt-working#if-youve-been-on-long-acting-synthetics-or-stacked-compounds. Volumetric tail and the “Only have 8 mg strips?” callout reframed to “Most prescriptions come as 8 mg strips”; same routing, less implication that 8 mg is the awkward edge case.
  • Custom Suboxone Dosing volumetric section rewritten end-to-end. Old version was Subutex-tablet-only with an H1 mid-page plus duplicate H2 headers. New version covers films and tablets explicitly with a validated math table (five dilution ratios from 2 mg / 8 mL through 8 mg / 160 mL), specific materials (oral syringe with 0.1 mL marks, glass mixing vessel, distilled water, optional USP propylene glycol at 3:1 water:PG), buprenorphine HCl solubility sourced to US Pharmacist, glass-vs-plastic storage stability sourced to PMC5517336, the TripSit volumetric calculator linked, and a bioavailability caveat surfacing the dissenting r/suboxone thread. Math table later reordered with 8 mg rows on top and a 400 mL / 0.02 mg/mL row added to match the 8 mg three-day tail.
  • Homepage Discord card given a full emerald-green emphasis treatment (border-2, fill, hover, all the parts of the amber crisis card) to read as “live, right now” at the same visual weight as the crisis card.

Infrastructure

  • Public changelog page at /about/changelog, generated from this CHANGELOG.md by scripts/sync-site-changelog.mjs. The sync runs as the npm run prebuild hook so the page rebuilds automatically on every CF Pages deploy. Idempotent: re-running with no upstream changes leaves the page’s last_updated date alone. Sits under Site & Community at sort=6.
  • CHANGELOG format change. Dropped the [Unreleased] prefix that came from the Keep-a-Changelog template. Date headers are now ## YYYY-MM-DD; the site doesn’t tag releases (every push to main deploys) so the unreleased semantics never carried meaning.

CLAUDE.md rule additions

  • Run the stop-slop pass on every prose edit, and report it. Every prose edit goes through the stop-slop ruleset before reporting done; the user-facing summary explicitly names that it ran and what it changed (or “no changes needed”). The point is visibility: a silent pass is indistinguishable from a skipped one.

2026-05-30

New pages

  • NAD+ IV Therapy (other-tools/nad-iv-therapy.md). Sourced reference: protocols, doses, methylation pairings, provider categories, and cost above the fold; honest evidence pass below (Blum 2022 pilot, the Springfield “90%” figure framed as marketing per NPR’s 2019 investigation, no RCTs in OUD/AUD, cellular-delivery question, Elysium critique with competing-product COI flagged, comparison to evidence-based alternatives). No clinic links.
  • Peptides for Opioid Withdrawal (other-tools/peptides-info.md). BPC-157, Selank, Semax, DSIP/Emideltide, TB-500, plus brief notes on KPV, GHK-Cu, Thymalin, Epitalon, Cerebrolysin. Per-peptide evidence labeled: Dick 1983/1984 for DSIP (the strongest withdrawal evidence, and the bar is low), Kost 2001 for the Selank/Semax enkephalin-degradation mechanism, no human RCT for BPC-157 or TB-500. Safety section on gray-market source quality (Finnrick / Janoshik testing-lab data), injection sterility, BPC-157 angiogenic cancer-promotion concern, WADA S0 prohibition. FDA PCAC July 2026 review noted as upcoming.
  • Endocrine Recovery After 7-OH and Kratom (post-acute/endocrine-recovery.md). Symptom-recognition lead → HPG/HPA mechanism → testing → recovery dynamics → treatment → supplements → parallel men-specific and women-specific sections → PAWS connection. Women’s section built to a strict integrity discipline: every women-specific claim sourced to a women-specific study (Daniell 2008, Abs 2000, Schmittner 2005, Zamboni 2019); the Bawor 2014/2015 reconciliation (women’s testosterone not significantly affected; cycle disruption is the salient finding) explained directly; literature gaps flagged rather than papered over. The women’s-section human-reviewer step from the brief was not done; flagged for community review before treating the page as final.
  • Black seed oil entry on vitamins-supplements (new row in the “Physical symptoms” chart + a dedicated prose entry) with explicit thin-evidence framing: one small uncontrolled 2008 Pakistani study (Sangi et al., n=35), rodent thymoquinone data, no human RCT.

Site structure and navigation

  • Homepage Live community section rebuilt as two cards mirroring the hot-list pattern. r/quitting7oh leads (searchable archive, longform stories); Discord follows. “About the community” remains as a small text link below.
  • Footer Community column added to the disclaimer row (4-up on desktop, 2x2 on tablet, stacked on mobile). Full-domain anchor text (reddit.com/r/quitting7oh, discord.gg/quitting7oh) for backlink SEO.
  • Category blurbs in src/lib/categories.ts brought current. other-tools dropped the stale naltrexone reference and gained NAD+ IV and peptides. post-acute swapped cravings/hormones placeholders for endocrine recovery and naltrexone. Homepage “Browse by topic” reads these at build time so the change propagates automatically.
  • post-acute sort cascade to accommodate endocrine-recovery at sort=7 in the Specific Symptoms cluster; kindling, long-term- outlook, and the four naltrexone-* pages bumped by 1.
  • Adjuncts pages reference each other coherently: vitamin C ↔ NAD+ IV ↔ peptides ↔ vitamins-supplements ↔ helper-meds. Tapering-7oh and the PAWS page route into the new adjunct pages where the symptom fit is right.
  • Endocrine recovery cross-links bidirectionally with PAWS and long-term outlook.

CLAUDE.md rule additions

  • Keep category blurbs in sync with content. When adding or moving a substantive page, the parent category’s blurb in src/lib/categories.ts is reviewed and updated in the same commit.
  • Keep CHANGELOG.md current. Substantive changes get logged here; the rule documents what counts as substantive and the format conventions.

2026-05-28

Page work

  • SOWS & COWS Guide rebased around SOWS as the primary at-home scale. Slug unchanged at /mat-suboxone/suboxone-cows; title and prose now lead with SOWS since most readers self-score through telehealth. Self-scoring and interpretation tables reordered to put SOWS first; threshold language and half-life / reminder sections made score-neutral. The mgm-15 page got the same SOWS-first framing in its COWS/SOWS callout.

2026-05-27

Page work

  • Bernese Method (Micro-Induction) restructured to put the technique front-and-centre. A two-target dose schedule (4 mg/day community low-and-slow vs 8 mg/day published BC 7-day) sits immediately after the intro, with variants and pharmacology below. Strip-cut math deferred to the Custom Suboxone Dosing page rather than duplicated. “Your opioid” / “original opioid” phrasing replaced with explicit 7-OH (or MGM-15 / MIT-A / pseudo) framing in the practical sections; “full agonist” preserved only where it’s the right technical term.
  • Tapering Off 7-OH front-loaded with a five-bullet “What to know before you start” summary covering the redose-discipline reality, the high-dose-easy / low-dose-grind shape, the jump-off endpoint, and the multiple endpoints. Phase table moved up alongside the bullets; the four-phase narrative descriptions stay below for readers who want depth.

Editorial passes

  • Footer AI disclaimer stop-slop pass: removed both em-dashes, the “augment” corporate phrasing, the stacked adjectives, and “frankly.”
  • ULDN page: BID → twice-daily cleanup.
  • Sidebar pinned shortcuts picked up “Thinking about using?” for the craving-spike entry point.

2026-05-26

Site structure

  • Beta banner removed from the layout. Site no longer marks itself as beta in the chrome.
  • Hero search box dropped from the homepage. The header search is the canonical entry point; the hero search was redundant visual weight on a page already dense with funnel cards.

2026-05-25

A big day. The stop-slop infrastructure landed, several new pages went up, the sidebar got a substantial reorganization, and a site-wide sourcing / voice pass touched dozens of files.

Stop-slop infrastructure

  • Vendored the stop-slop ruleset to docs/stop-slop/ (Hardik Pandya’s MIT-licensed skill snapshot, with project-local additions documented in the snapshot’s CHANGELOG). CLAUDE.md now points to it as the canonical anti-AI-writing-pattern source rather than duplicating ~500 lines of pattern rules inline.
  • Site-wide stop-slop sweep against the updated ruleset (mechanical + voice passes). Touched compounds and MAT pages most; the mgm-15 and suboxone-info pages each got their own follow-up voice pass.

New pages

  • How AI Was Used (about/how-ai-was-used.md). About-section page documenting how the site uses AI in drafting. The about category was renamed and the medical disclaimer tightened in the same pass.
  • Paths Off 7-OH (start-here/paths-off.md). Consolidates the six community-discussed paths off (Suboxone, SR-17, leaf taper, helper-meds cold turkey, etc.) into one decision-support page. Replaces scattered enumeration across multiple pages.
  • Tapering Off 7-OH (for-you/tapering-7oh.md). Initial creation: phase mapping (early cuts → middle range → lower-dose plateau → jump-off), variance acknowledged, multiple endpoints named. The front-load happened on 2026-05-27 (above).
  • Where the Site Stands (about/where-we-stand.md). Position statement (shipped 2026-05-24; logged here for cross-reference with the about-category work).
  • Naltrexone family moved from other-tools/ to post-acute/. Four pages (overview, normal-dose, LDN, ULDN) plus the existing links from PAWS and depression-and-anhedonia. The framing shift is editorial: naltrexone is post-acute support, not a way to come off opioids.
  • Sidebar reorganized with collapsible category groups and a reference-section separator between the recovery-focused categories (Start Here, For You, For Loved Ones, MAT/Suboxone, Adjuncts, Post-Acute) and the reference-focused ones (Compounds, Pharmacology, Resources, Site & Community).
  • Sidebar pinned shortcuts and sub-groups in long categories. Pinned-shortcuts rail at the top (configurable list); sub-groups inside MAT/Suboxone, For Loved Ones, Adjuncts, Post-Acute so the long lists don’t read as one flat dump.
  • Homepage layout tightened. Added Paths Off 7-OH and the For Loved Ones funnel cards. Mobile sidebar wired up. COWS rubric on suboxone-info converted to a 3-column table.
  • Category emojis and 🆘 replaced with Lucide icons across the sidebar, category index, and the floating Crisis button. The Crisis button now uses LifeBuoy.

Theme and design

  • Zinc as default theme variant; light-theme rework; picker tooltip added so the dropdown is discoverable.
  • OG image dropped in favor of a clean text-only social card. Readers in withdrawal don’t need a banner image every time a page is shared.

Meetings widget

  • Next-meeting widget added with structured-data output and a full meetings-table component for the schedule page. Single source of truth in src/data/meetings.ts. A follow-up later in the day added a “Next up at TIME” line when the current meeting is live.

Content / sourcing corrections

  • 7-OH binding-affinity vs antinociception-potency conflation corrected on the 7-OH compound page. Earlier copy had inflated the binding-affinity numbers using antinociception-assay potencies from animal studies, which is not what those studies measured.
  • “Stop calling 7-OH and SR-17 ‘an opioid’” reframe. Both are mu-opioid-receptor agonists, but calling them straight opioids carries pharmacology baggage (full-agonist OD risk profile, legacy-opioid framing) that doesn’t fit. New framing: receptor-agonist that “walks and talks like” an opioid.
  • Protocol-first rewrites of dopamine, depression-and-anhedonia, naltrexone, SR-17, and mega-dose-vitamin-C pages. Lead with the practical protocol; push the long-form pharmacology and rationale below.
  • mgm-16 forensic claims tightened on the MGM-16 compound page; the speculative “If you’ve encountered MGM-16 in a product” section was stripped, the California paper reference reframed as a single unsourced mention, and “I” framing removed.

CLAUDE.md rule additions

  • Don’t make multi-year claims about the synthetics. Concentrated 7-OH emerged in U.S. consumer markets around 2023; the kratom- synthetic recovery community took shape in early 2024. No reader has multi-year dependence on the synthetics specifically. Claims like “years of stacked use” should reframe as severity, not time.
  • Soften MAT-fit certainty. The pages don’t get to declare which path is right for any individual reader.

2026-05-24

New pages

  • The Pink Cloud (post-acute/pink-cloud.md). Names the honeymoon-stretch phenomenon of early recovery: weeks-to-months window of unusual mood lift and energy after acute resolves, followed by settling into a more grounded baseline. Not a sign recovery is failing; documented pattern.
  • Where the Site Stands (about/where-we-stand.md). Position statement on the site’s posture toward vendor capture, the kratom industry’s regulatory lobbying, AI use in drafting, monetization, data, and editorial bias. Plain language; no hedging.

Page work

  • Suboxone Rapid Taper picked up the rapid-taper schedule tables (initial version, before the 2026-05-27 restructure and the 2026-06-04 collapsible / bottom-of-taper additions). Micro-induction practical sourcing added alongside; the framing is “Suboxone is one path, not the default first-attempt tool.”
  • Suboxone (suboxone-info) got three practical induction-protocol notes; a high-dose-bupe-rescue note for precipitated withdrawal (with the Laxton 2025 case-report cite); the COWS/SOWS section trimmed to a reference + link to the dedicated COWS/SOWS page; cross-link to COWS in induction; the practical-tips “wait an hour after waking up” tip; SOWS PDF + SAMHSA TIP 40 references added for full sourcing.

Editorial passes

  • Footer AI disclaimer evolution. Sharper second paragraph (failing-system framing, bigger-boats line, callback structure); later same day trimmed the “Don’t like that?” sidebar so the disclaimer reads tighter.
  • Site-wide crisis-callout and medical-advice cleanup. Emoji prefixes stripped from callouts site-wide. An AI-slop paragraph on withdrawal-help got rewritten. Withdrawal-help opener tightened. The “On bans and regulation” section on Where the Site Stands trimmed to non-position-only content (the page’s job is the site’s posture; the wider regulation debate isn’t this site’s fight).

2026-05-23

shadcn/ui migration (experiment/shadcn branch)

Full React + shadcn/ui rebuild of all interactive components. Shipped as 7 focused commits on experiment/shadcn rather than main; merge to main after visual review in a browser.

  • Phase 0 — foundation. Added @astrojs/react, React 19, lucide- react, class-variance-authority, clsx, tailwind-merge, the radix-ui unified package. Created components.json (shadcn config), src/lib/utils.ts (cn helper), src/components/ui/ directory. Defined HSL theme variables for 8 variants in src/styles/global.css via the Tailwind v4 @theme inline {} pattern.
  • Phase 1 — theme picker. Replaced ThemeToggle.astro (icon-cycle button) with ThemePicker.tsx: a shadcn DropdownMenu with two radio groups (Appearance: System/Light/Dark, Color: 8 variants). Both axes persist to localStorage; pre-paint script applies both before first render so no flash on either mode or variant switches.
  • Phase 2 — sidebar. First tried the official shadcn Sidebar component but its fixed inset-y-0 left-0 positioning fought this site’s centered max-w-[88rem] layout. Replaced with a hybrid: shadcn Sheet for the mobile drawer (gets Radix focus trap, scroll lock, ESC, ARIA for free), plain <aside> for desktop sticky rail inside the centered container. Astro hamburger dispatches a 'toggle-sidebar' window event the React sidebar listens for.
  • Phase 3 — search + back-to-top. SearchBox.tsx uses shadcn Command (cmdk) inside a CommandDialog opened via the button or ⌘K; Pagefind runs the actual queries via the existing runtime-import pattern. BackToTop.tsx uses shadcn Button + ArrowUp icon, hydrates with client:idle.
  • Phase 4 — Callout/Breadcrumbs/BetaBanner/Footer. Callout uses shadcn Alert with three variants (info=Info, warning=AlertTriangle, medical=Stethoscope). Breadcrumbs uses shadcn Breadcrumb. BetaBanner is a custom React component with sessionStorage dismiss. Footer is a plain React port using semantic tokens (bg-muted, text-foreground, text-primary) so it follows theme-variant changes.
  • Phase 5 — TOC + TocMobile. Toc is a plain right-rail nav with semantic tokens. TocMobile uses shadcn Collapsible (Radix) instead of native <details>. Fixed a missing import * as React from "react" in the CLI-installed collapsible.tsx that broke SSR.
  • Phase 6 — cleanup. Deleted all superseded .astro versions (Sidebar, ThemeToggle, SearchBox, BackToTop, Callout, Breadcrumbs, BetaBanner, Footer, Toc, TocMobile). Updated src/pages/sitemap.astro to import the new React Breadcrumbs and dropped the source_channel/manual rendering (those fields are gone with the Discord ingest retirement). Added a “UI components: shadcn/ui + React” section to CLAUDE.md documenting the new conventions, theme picker storage keys, semantic tokens, and the hamburger event bridge.

Bundle size: about +100 KB gzipped for the React runtime + Radix on pages with interactive islands. Acceptable trade-off for the consistent shadcn design system, accessible primitives, and the theme-picker UX.

Retired the Discord-export ingest pipeline

The site is now the sole source of truth for content. The ingest pipeline that originally imported Discord channel exports into src/content/ has been removed to prevent future sessions from accidentally re-ingesting and clobbering editorial work.

  • Deleted: scripts/ingest-discord.mjs, scripts/channel-mapping.json, the entire imports/ directory (raw Discord exports + the HTML source files for the pharmacology pages).
  • Removed npm run ingest and npm run ingest:dry from package.json. The link:compounds script stays — it operates on current site content and isn’t tied to ingest.
  • Schema cleanup: dropped source_channel and manual from the content collection schema in src/content.config.ts. Both fields only existed to serve the ingest pipeline: source_channel was provenance from the originating Discord channel, manual told the ingester not to overwrite an editorially-restructured page. With no ingester to talk to, they were dead weight.
  • Front-matter sweep: stripped source_channel: and manual: lines from all 46 content files. The site rebuilds cleanly with the trimmed schema.
  • Docs cleanup: updated src/content/README.md front-matter table to drop the removed fields and add a row for the wide field that was already in use. Updated CLAUDE.md to remove the ingest references in the “Editing content” section and the build commands block.

User-facing Discord references (the homepage card, the /resources/community page, “Join the Discord” callouts, the discord.gg/quitting7oh invite link) are kept — these are community-pointer content, not data sources, and they’re how readers find live help.

Also retired: scripts/convert-pharma-html.mjs (the one-shot HTML-to-Astro converter for the pharmacology charts). Its input folder imports/_html-source/ was part of the deleted imports/ tree, and the Astro components it produced (MinorAlkaloids.astro, MorphineVsKratom.astro) are already committed and stable. The generator-attribution comments at the top of those components have been replaced with plain descriptions.

  • CLAUDE.md updated with a “Link every third party we name” rule. When we cite an outside organization, hotline, treatment program, tool, credential, government program, law, or book, link it on first mention (internally if we have a page, externally otherwise). See the rule for the curated list of canonical URLs for the most common references (SAMHSA, 988, DV/Childhelp hotlines, CARF, NARR, Medicaid, MHPAEA, ADA, FMLA, etc.).
  • Audit and sweep across all new pages for unlinked third-party callouts: Salvation Army ARCs, CARF, Joint Commission, NARR, Oxford House, Medicaid, Vivitrol, VA, FQHCs, MHPAEA, ADA, FMLA, HIPAA, ACA, Department of Labor, Wage and Hour Division, EEOC, 988 Lifeline, DV Hotline, Childhelp, Poison Control, Open Path Collective, Inclusive Therapists/Therapy for Black Girls/Latinx Therapy, NA, AA, Heroin Anonymous, The Phoenix, In The Rooms, Al-Anon, Nar-Anon, Families Anonymous, Allies in Recovery, Beyond Addiction and Get Your Loved One Sober (book links). Each now has a link on first mention.
  • Prominent FMLA-eligibility callout at the top of both FMLA pages (for-you/fmla-ada-job and for-loved-ones/fmla-workplace). The 12-month / 1,250-hour / 50-employees-within-75-miles requirements are the biggest gotcha; readers commonly plan around FMLA without realizing they don’t qualify. The warning is now the first thing they see, with a pointer to state programs as the alternative.
  • New page: MAT & Your Professional License. Most jobs have no business in your medical info — but a defined set of regulated professions (CDL/DOT FMCSA, FAA pilots and ATC via the HIMS program, law enforcement, armed security and firearms permitting, healthcare licensure via state PHPs, federal security-clearance roles, heavy machinery/safety-sensitive positions, school bus and transit operators) treat MAT use as a licensure issue distinct from employer policy. Page covers each profession’s regulatory landscape, the practical “what to do before disclosing” sequence, and flags Vivitrol (extended-release naltrexone) as the non-controlled-substance option that sidesteps many regulatory issues that buprenorphine and methadone trigger. Cross-linked from suboxone-for-7oh, for-you/treatment-rehab, for-you/fmla-ada-job, for-you/start-here, and for-loved-ones/treatment-options.
  • for-you/ sort order updated to slot the new MAT-job page between fmla-ada-job (3) and mutual-aid: mat-and-your-job (4), mutual-aid (5), sober-living (6).

Two new sibling sections: For You + For Loved Ones

  • New top-level category for-you (💚) — practical recovery resources for the person in recovery: Treatment & Rehab, FMLA/ADA/Job, Mutual Aid & Recovery Groups, Sober Living Homes, plus a section hub at /for-you/start-here.
  • New top-level category for-loved-ones (🫂) — for family, partners, and friends of someone struggling: What to Expect, How to Talk (with a CRAFT primer), Boundaries Without Punishment, Safety (incorporating the full naloxone walkthrough), Asking Them to Leave the House, Treatment & Rehab (family POV), FMLA & Workplace Protections, Taking Care of Yourself, Support Groups for Family & Friends, plus a section hub at /for-loved-ones/start-here.
  • Old /start-here/for-loved-ones page retired. Content redistributed across the new section’s pages where it fits topically; the substance explainer cross-links to /compounds/7-oh instead of duplicating. Channel mapping entry for for-loved-ones removed from scripts/channel-mapping.json to prevent re-ingest from clobbering the new editorial section. Inbound link in start-here/welcome.md updated.
  • Sidebar ordering — both new sections sit right after Start Here, with For You first (primary audience) and For Loved Ones second.
  • Mutual aid directory in /for-you/mutual-aid leads with Kratom Anonymous as the most directly applicable fellowship for this community, followed by Quitting Kratom Support (TIAWO), opioid-specific fellowships (NA, Heroin Anonymous), and the broader options (SMART, Refuge Recovery, Recovery Dharma, The Phoenix, In The Rooms, LifeRing, Women for Sobriety, Celebrate Recovery, AA, HAMS). Family-side directory in /for-loved-ones/support-groups covers Nar-Anon, SMART F&F, Learn to Cope, TIAWO (welcomes family), Al-Anon, Families Anonymous, ACA, GRASP, plus a short CRAFT-learning sub-section pointing to Allies in Recovery and the Foote/Meyers books.
  • New /resources/meeting-schedules page — full Kratom Anonymous weekly schedule with day, time, format, cutt.ly shortlink, and resolved Zoom URL. Linked from both /for-you/mutual-aid and /for-loved-ones/support-groups.
  • MAT relationship: both treatment pages link out to existing /mat-suboxone/*, /other-tools/low-dose-naltrexone, /other-tools/ultra-low-dose-naltrexone, and /resources/quickmd-info rather than duplicating that content. Family page also points readers to the corresponding For You page so they can see what their loved one is navigating, and vice versa.
  • Substance framing: new pages consistently distinguish kratom leaf (sometimes a valid taper tool) from concentrated 7-OH / MGM-15 / MIT-A / pseudo synthetics. Polysubstance warnings (alcohol, benzos, gabapentinoids) with SAMHSA + findtreatment.gov routing appear on every page where withdrawal, detox, or medical risk is discussed.
  • House-style language: family pages use “person with a substance use disorder” / “your loved one” / “the person you love” rather than “addict.” Recovery-side pages meet the reader where they are without assuming readiness, abstinence, or shame. “Server” used only for Discord references; “community” / “site” for everything else.

2026-05-21

Site bootstrap & initial content

  • New Astro 5 project with content collections, MDX, Tailwind v4 (via @tailwindcss/vite), typography plugin, Pagefind search.
  • Three-state dark mode (systemlightdark): toggle in the header, inline pre-paint script to prevent flash, matchMedia listener for live OS-theme changes while in system mode. Tailwind v4 @custom-variant dark powers the class-based theming.
  • Self-hosted Inter via @fontsource-variable/inter — no Google Fonts request.
  • Shiki dual-theme code blocks (github-light + github-dark), swapped via the .dark class.
  • External-link rehype plugin — auto-adds target="_blank", rel="noopener noreferrer", and a CSS-driven indicator icon to off-site links.
  • Heading-anchor rehype plugin — appends a hover-revealed # link to each H2/H3/H4. The visible # is rendered via a CSS ::before pseudo-element so it never enters the DOM as text (which Astro’s TOC extractor would otherwise pick up).
  • Site structure: 7 top-level categories — Start Here, Active Withdrawal, Compounds, MAT / Suboxone, Other Tools, Post-Acute, Resources. Sidebar nav auto-populates from content collection entries; URL structure is /<category>/<slug>.
  • Homepage: calm hero, prominent CTA for active-withdrawal SOS, category grid with page counts, hero search.

Ingest pipeline (Discord exports → site content)

  • scripts/ingest-discord.mjs — reads Discord channel exports from /imports/, parses messages, strips per-message metadata, joins them into clean markdown, writes to src/content/<category>/<slug>.md.
  • scripts/channel-mapping.json — maps Discord channel slugs to site categories with optional title overrides.
  • Multi-channel exports supported — a single input file containing multiple # #channel-name sections splits into multiple output files.
  • CLI flags: --dry-run, --file <path>, --in <dir>, --out <dir>, --verbose. Files prefixed with _ and README.md/index.md are skipped (treated as fixtures or exporter manifests).
  • Two-pass discovery for cross-linking: pass 1 scans every input file’s channel header to build a knownChannels set; pass 2 transforms bodies and links **#channel-name** and bare #channel-name references only when a corresponding site page exists (or will exist after this run).
  • Fuzzy channel-name matchingnormChannel() strips non-alphanumerics and lowercases, so #mgm-15 / #mgm15 / #7oh / #7-oh all resolve to the same canonical page.
  • Discord syntax stripping in body transform:
    • *(edited)* markers (both inline and on header lines)
    • *Reactions:* … reaction summary lines
    • -# … Discord subtext lines
    • :emoji: shortcodes → unicode (via emojiMap in the config)
    • <@123> and bare @username mentions → anonymized
  • Chronological message ordering — sorts by parsed message timestamp (oldest → newest) regardless of input direction. Different Discord exporters produce different orderings; sorting handles both.
  • Code-fence-aware regex for title derivation and channel-ref conversion (Python comments like # foo inside code blocks no longer get mistakenly picked up as headings or channel references).
  • Auto-derived front matter: title (from channel override → first H1 → titleized channel name), description (first paragraph, truncated to 120 chars), last_updated (most recent message timestamp), category (from mapping), source_channel (the Discord channel name).
  • manual: true front-matter flag — when set on an existing src/content/ file, ingest skips that file even if its source channel appears in /imports/. Lets you protect editorially-restructured pages from being clobbered.
  • Description preservation on re-ingestexistingDescription() reads the on-disk file’s front matter and prefers a non-empty hand-curated description over the auto-derived one. Makes it safe to hand-write descriptions even on non-manual files.
  • Compound auto-linker (scripts/lib/compound-linker.mjs, scripts/link-compounds.mjs) — turns the first mention of each known compound (7-OH, MGM-15, MIT-A/DHM, pseudoindoxyl, Cat’s Claw) on each page into a link to its compound page. Self-link prevention (a compound page doesn’t link to itself). Skips code blocks, inline code, existing markdown links, headings, blockquotes. Idempotent. Integrated into the ingest pipeline AND runnable standalone via npm run link:compounds.
  • Pre-commit hook at .githooks/pre-commit — runs markdownlint-cli2 on staged content files. Loose config in .markdownlint-cli2.jsonc.

Content (ingested + editorial)

Imported from Discord exports (20 pages, ingested via the pipeline)

CategoryPages
start-herewhat-to-expect, for-loved-ones
active-withdrawalhelper-meds-info, quitkit-info, vitamins-supplements
compoundscats-claw, mit-a-dhm, mgm15, pseudo
mat-suboxonesuboxone-info, suboxone-cows, suboxone-custom-dose, suboxone-isnt-working, suboxone-rapid-taper, suboxone-risks, sublocade-brixadi-info
other-toolslow-dose-naltrexone, mega-vit-c-info, sr17018-info, tapering-with-leaf
post-acutewhat-is-paws, sleep-recovery
resourcesquickmd-info

Hand-written editorial pages (manual: true)

  • welcome.md — 5.8 KB orientation page: who the site is for, what it is/isn’t, 6 contextual starting points (active withdrawal, considering MAT, post-acute, understanding compounds, loved ones, researchers), Discord + subreddit links, closing reassurance.
  • sos-resources.md — emergency-ready SOS page: 988/911 callout, Discord/subreddit links up top, “in the next hour” action list, hour- by-hour timeline table, three paths from here (tough-it-out vs. Suboxone vs. SR-17018), explicit ER red flags, sleep/food/mindset sections, closing reading list.
  • resources/community.md — full page on the Discord (discord.gg/quitting7oh) and subreddit (r/quitting7oh), with a “which to use when” comparison table, anonymity note, “how to help” section.

Editorial expansions to existing pages

  • suboxone-info.md (now manual: true) — added three major sections:
    • Why we start low — receptor occupancy: PET-imaging table showing the bupe receptor-occupancy curve flattens past 8 mg (2 mg ≈ 50–60%, 8 mg ≈ 85–90%, 16 mg ≈ 92%, 32 mg ≈ 95%); the cost of starting at 16+ mg is a much longer/harder taper for negligible additional coverage.
    • About taper duration: 5–14 days is the realistic range for this community (not weeks/months). Per-dose-range table. Corrected after user feedback (“None of our tapers is ever weeks or months”).
    • Long-term maintenance is a real option: explicit “no shame”; pharmacological framing (this community is short-taper-focused because 7-OH responds to short tapers, not because long-term is failure); when to consider Sublocade/Brixadi instead; pointer to r/suboxone for maintenance discussion.
  • suboxone-cows.md (now manual: true, renamed to “COWS & SOWS Guide”) — added full SOWS (Subjective Opiate Withdrawal Scale) section: 16 symptom items, 0–4 scoring, severity bands, induction threshold (SOWS ≥ 17 ≈ COWS ≥ 12), guidance on which scale to use in which context (COWS for clinician-assisted, SOWS for solo home induction).
  • vitamins-supplements.md (now manual: true) — restructured: H1 + disclaimer first, Quick recommended list section with 5 scannable tables (Start with these / sleep / mood-and-PAWS / physical symptoms / avoid), then the detailed sections with dosing and citations.

Homepage callout — nuanced

The “trust the clinician” callout on the homepage was rewritten to acknowledge that for some MAT decisions (Suboxone starting doses, taper pacing) the community has lived experience worth bringing to the prescriber conversation, without abandoning the broader “clinician knows your situation” framing.

Site-wide language fixes

  • “server” → “community”/“site” — 41 references across 13 imported pages reviewed case-by-case. “Discord server” kept where explicitly Discord; everything else mapped to “this community” (when referring to people) or “this site” (when referring to editorial focus). Changes made in /imports/ so they survive future re-ingestion.
  • Pagefind integrated. Lazy-loaded only when the user focuses a search input — visitors who never search download zero JS for it.
  • Header search (<SearchBox variant="header">) and hero search on the homepage (<SearchBox variant="hero">). Both wired to the same Pagefind client.
  • Dev-mode message improved — instead of “Search index not available (was the site built with npm run build?)”, it now reads “Search is only available on the deployed site. To test locally, run npm run build && npm run preview.”
  • Index built into dist/pagefind/ as the post-Astro step of npm run build. Currently indexed: 27 pages, ~3,636 words.

Front matter & descriptions

  • Schema in src/content.config.ts — typed with zod: title, description, category, last_updated, source_channel, sort, draft, manual.
  • All 27 page descriptions tightened from auto-generated 150–160-char snippets (which were getting cut off in cards/snippets) to hand-written ~80–110-char summaries.
  • Ingest auto-truncation lowered from 160 → 120 chars for future imports.

”Edit this page on GitHub” fix

  • Astro 5’s glob content loader returns doc.id without the file extension, so my old editOnGithubUrl(doc.id) produced …/start-here/welcome (404) instead of …/start-here/welcome.md. The page route now uses doc.filePath and slices off src/content/ to get the actual relative path with extension.

Deployment infrastructure

Two supported deploy paths, both wired up:

Option A — Cloudflare Pages (managed, free):

  • wrangler.toml with pages_build_output_dir = "dist".
  • public/_headers — security + cache headers.
  • public/_redirects — placeholder for permanent redirects.
  • Build command npm run build, output dist/, Node 22.

Option B — Docker + GHCR + self-hosted:

  • Dockerfile — multi-stage: node:22-alpine builds Astro + Pagefind, output copied into nginx:1.27-alpine. Includes HEALTHCHECK for orchestrators. Listens on :8080.
  • docker/nginx.conf — gzip, immutable cache for /_astro/*, short cache for /pagefind/*, security headers (CSP-adjacent set, HSTS deferred to Caddy), trailing-slash routing via try_files, /healthz endpoint, hidden version banner.
  • .dockerignore — excludes node_modules, dist, imports, CI/docs, etc.
  • .github/workflows/docker-publish.yml — multi-arch (linux/amd64 + linux/arm64) build on every push to main, publishes to GHCR as ghcr.io/<owner>/<repo> with tags latest, sha-<short>, semver (v*.*.*), and PR branches. Includes build attestation, provenance, and SBOM.
  • docker-compose.yml — reference stack with site (the nginx container), caddy (TLS + HTTP→HTTPS + www→apex), and an optional watchtower that polls GHCR every 5 min.
  • Caddyfile — reverse-proxy config: automatic Let’s Encrypt via ACME, HTTP/3 enabled, HSTS, www→apex canonical redirect.
  • docs/deploying.md — full server-setup walkthrough: VPS provisioning, DNS, Docker install, GHCR auth (public + private flows), starting the stack, day-to-day operations (push, rollback, pinning), logs/troubleshooting matrix, hardening, scaling notes.

Bugs fixed during the session

  • Ingest’s title regex matched inside code fences (Python comment starting with # got picked as the page title). Now strips fenced code blocks before scanning for the first H1.
  • Channel reference double-replacement**#suboxone-info** was being wrapped twice ([[#suboxone-info](/...)](/...)). Added [ to the exclusion class in the bare-reference regex so the bracketed text inside an already-formed link doesn’t re-match.
  • Discord message-header regex too strict — failed on headers with trailing *(edited)*. Now accepts an optional *(edited)* suffix.
  • Reverse-message-order assumption was wrong for one of the export formats — caused the H1 to end up buried mid-document. Now sorts by timestamp regardless of source order.
  • *Reactions:* 👍 3 lines were rendering as literal text on the site. Now stripped during body transform.
  • -# Discord subtext lines rendering as literal text. Now stripped.
  • SKIP14 literal text leaking into rendered pages from the compound-linker’s mask/restore cycle when a blockquote contained a markdown link (nested masks). Token format changed from SKIP${n} (whitespace-delimited) to \x00SKIP${n}\x00 (U+0000- delimited, can’t appear in source) and restore now loops until stable to unwind nested masks.
  • Compound pages were self-linking (“7-OH” on /compounds/7-oh linked to itself). linkCompounds() now takes a selfUrl and skips that compound on its own page.
  • TOC entries had trailing # because the heading-anchor rehype plugin added a text-node # child that Astro’s heading extractor picked up. The # is now rendered via CSS ::before on the anchor element.
  • Bold text invisible in dark mode because the Tailwind Typography plugin’s --tw-prose-bold defaults to near-black. Added dark:prose-invert to the <article> wrapper.
  • Pagefind dynamic import failed at build time because /pagefind/pagefind.js doesn’t exist until the post-Astro Pagefind step runs. URL is now constructed at runtime so Rollup can’t statically analyze it.
  • src/content/README.md was being picked up as a content entry and failing zod validation. Glob pattern now excludes **/README.md.
  • .astro/content-assets.mjs missing after a hard cache clean — documented the safe-clean sequence (rm -rf dist .astro node_modules/.vite && npx astro sync) in the prior conversation.

Docs

  • README.md — local dev, ingest workflow (Paths A + B), adding a page, adding a category, both deploy options with a decision table, what the site won’t do.
  • src/content/README.md — 5-step “add a page” guide, full front- matter reference table (including the new manual flag), available markdown features, callout usage in MDX, what not to do.
  • imports/README.md — non-developer Discord-export workflow, multi-channel exports, idempotency, the _-prefix skip convention, the manual: true flag for protecting editorial work.
  • docs/deploying.md — full server-setup walkthrough (already listed under Deployment).

Pharmacology section (new category)

  • New top-level category: Pharmacology (🔬) — for deeper science content beyond the practical compound overviews.
  • pharmacology/minor-alkaloids.mdx — Kratom’s Minor Alkaloids: Serotonergic & Adrenergic Activity Beyond the µ-Opioid Receptor. The 7-column chart of mitragynine vs. paynantheine, speciogynine, speciociliatine, corynantheidine, 9-hydroxycorynantheidine, and mitraphylline across µ-opioid / 5-HT / α-adrenergic receptor systems. Recovery-reader intro at the top routes anyone in acute withdrawal to the right pages elsewhere on the site.
  • pharmacology/morphine-vs-kratom.mdx — Morphine vs. Mitragyna Alkaloids: Structure, Modification & µ-Opioid Receptor Binding. Side-by-side structural pharmacology.
  • scripts/convert-pharma-html.mjs — one-shot converter that extracts the <style> and <body> from the source HTML, drops the Google Fonts link, and remaps the doc’s CSS variables (--paper, --card, --ink, --em, etc.) to our site palette (zinc + accent- teal) in both light and dark mode. Output is two Astro components under src/components/pharmacology/ whose styles are auto-scoped by Astro so they don’t leak. Original layout (2000px-wide reference sheet with the 7-column grid, molecule SVGs, receptor activity cards, polypharmacology map, caution + clarification panels, source citations) preserved intact. Horizontal-scroll on narrow viewports so the chart stays legible on mobile.
  • Each page also includes a “Reference, not advice” callout at the bottom, and manual: true so the MDX wrappers don’t get clobbered by ingest.

Pharmacology charts — wide: true layout

The two pharmacology reference charts (1200px min-width) wouldn’t fit inside the standard 832px content column. After two iterations:

First try — full-bleed calc(50% - 50vw) escape: broke out of the prose column but pulled the chart under the left sidebar. Reverted.

Final fix — new wide: true front-matter flag:

  • Added wide: z.boolean() to the content schema.
  • DocLayout checks the flag: when true it keeps the sidebar (so site navigation still works on pharma pages) but hides the TOC and removes the max-w-[52rem] content-column constraint.
  • The outer container expands from max-w-[88rem] (1408px) to max-w-[112rem] (1792px) on wide pages, giving the chart enough room next to the sidebar (~1408px of usable main width).
  • The chart’s own max-width: 1600px caps it on huge displays; min-width: 1200px with overflow-x: auto provides horizontal scroll inside the chart wrapper on viewports narrower than 1200px.
  • Both pharmacology MDX pages now set wide: true.

Header, footer, and beta banner stay at the standard max-w-[88rem] so the chrome doesn’t sprawl. Slight asymmetry on 1792px+ displays (content extends past chrome) but the chart fits cleanly.

Wider site layout

Bumped the layout widths across the board for a less constrained feel on modern displays (laptops 1440px+, desktops 1920px+):

WhatWasNow
Outer container (header/footer/main)1280px1408px
Doc content column704px832px
Category index inner column768px832px
Sitemap container1024px1152px
Homepage hero + medical-disclaimer896px1024px
Homepage category grid3-col max4-col at xl

Content prose stays in a comfortable line-length range (832px = roughly 85-95 chars per line at 16px Inter), but the page itself fills more of modern wide screens.

  • New /sitemap page at src/pages/sitemap.astro — human-readable index of every page on the site, grouped by category, with title + source channel + description for each entry, and an “editorial” badge on manual: true pages. Cross-links the search-engine sitemap at /sitemap-index.xml for crawlers.
  • Footer link bar added at the bottom of every page: Site map · Community · GitHub.

Honest ER framing on the SOS page

  • The “ERs are required to stabilize you” paragraph was rewritten to keep the legal facts (EMTALA, no legal trouble for disclosure, on-site Suboxone induction) but acknowledge the lived reality that not every ER and not every doctor handles withdrawal well. New section gives readers concrete agency tools:
    • Stick to medical facts and numbers (COWS score, symptoms)
    • You can ask for a different provider, or escalate to the attending
    • Bring someone if possible — presence changes how staff behave
    • AMA discharge is allowed when you’re not in active emergency
    • A bad ER doesn’t mean medical care won’t help; a telehealth Suboxone visit may be a better path

ULDN (Ultra-Low-Dose Naltrexone) — new page

  • other-tools/ultra-low-dose-naltrexone.md added (manual editorial). Companion to the existing LDN page. Covers the μg-range dose space, the dual-signaling-model mechanism, and the two community use cases: smoothing the bottom of a Suboxone taper, and reducing tolerance during longer-term bupe/Subutex maintenance.
  • The LDN page now ends with an explicit “Not the same as ULDN” entry pointing readers to the new page (LDN is mg-range, after-withdrawal; ULDN is μg-range, taken with opioids). Added in both imports/ and src/content/ so the cross-link survives any future re-ingest.
  • New entry in scripts/channel-mapping.json so #ultra-low-dose-naltrexone channel references route correctly.

7-OH page filled in (was a placeholder)

The site is named after this compound, but the compounds/7-oh.md page had been sitting as a stub. Replaced with a real, manual-editorial page covering:

  • What 7-OH actually is (alkaloid in Mitragyna speciosa, naturally trace amounts, sold concentrated/semi-synthetic at retail).
  • Pharmacology: µ-receptor binding affinity (Ki ~13-17 nM, ~10× tighter than mitragynine), partial agonist with meaningful intrinsic activity, mu-dominant.
  • Plasma half-life ~100 minutes — short by opioid standards.
  • A side-by-side comparison table: leaf kratom vs. concentrated 7-OH. This is the single most important framing for new readers.
  • Acute withdrawal timeline (table) and the SNRI-like overlay from stacked products.
  • “Why 7-OH is actually tapereable” — the same short half-life and mu-dominant binding that make it easy to get hooked also make it respond well to short Suboxone tapers.
  • Common retail forms (tablets, shots, pseudo, stacked products, raw powder).
  • Marketing claims to be skeptical of (“non-addictive”, “all-natural”, “doesn’t cause respiratory depression”).
  • Three real paths to stopping, with cross-links.

Cross-linked from welcome, what-to-expect, SOS, suboxone-info, MGM-15, LDN, and pharmacology pages via the existing compound auto-linker.

Kratom framing — leaf vs. synthetics

Site-wide audit found several “don’t use kratom” statements that wrongly grouped leaf in with concentrated 7-OH / synthetics. Distinction now made consistently:

  • The compound that brought you here (7-OH, MGM-15, MIT-A/DHM, pseudo, stacked synthetics) — never redose during withdrawal or active recovery.
  • Plain kratom leaf — a planned, deliberate taper tool for some people in this community (see #tapering-with-kratom-leaf); not a rescue medication and not improvised at 3 a.m.

Updated in: vitamins-supplements.md (both “Avoid” sections), sos-resources.md (“Don’t” list), suboxone-info.md (taper bullet + reminder callout), imports/suboxone-isnt-working.md (“don’t redose” list), imports/suboxone-rapid-taper.md (“seek help” trigger).

Added a row of community links to the homepage hero, just below the SOS CTA:

  • 💬 Discord: discord.gg/quitting7oh — real-time community
  • 📖 r/quitting7oh: searchable, slower, good for stories
  • → About the community — links to the deeper community page

Also fixed the SOS CTA: it was pointing at the /active-withdrawal category index; now it links straight to /active-withdrawal/sos-resources where someone in acute distress actually wants to land.

Site-wide beta banner

  • BetaBanner.astro mounted at the top of every page (via BaseLayout.astro, just below the skip-link). Amber strip, warning icon, full text: “Beta — This site is still being verified. AI tools were used to help organize and clean up content that was originally written and fact-checked by humans, but not every page has been fully reviewed yet. Use at your own risk.”
  • Dismissable per session via sessionStorage so a return visitor in the same session doesn’t have to look at it, but a fresh visit always shows it — the warning matters enough that a new reader should always see it once.
  • Renders correctly in both light (amber-50 bg, amber-900 text) and dark (amber-950/50 bg, amber-100 text) modes.

Still in flight / next up

  • compounds/7-oh.md is still a placeholder; the real Discord export for that channel hasn’t been provided.
  • SITE.repo in src/lib/site.ts assumes the repo is at github.com/quitting7oh/quitting7oh.org — update once the canonical repo exists. (Affects “Edit on GitHub” links.)
  • Pharmacology pages might want a “minor alkaloids ⇄ compounds” cross-link strategy — right now they live in their own category but compound pages don’t yet link out to the deeper reference. Worth a follow-up pass to wire those connections explicitly.
Last updated: View source on GitHub