/* global React */ // Blog post — data-driven from assets/posts.json (?post=slug) const { useState, useEffect } = React; const NS_BP = window.GamekeepersCottageDesignSystem_070bc7; const { Button, Badge, Eyebrow, Card } = NS_BP; const Photo = window.GKPhoto; const useShell = window.GKuseShell; const IMG = window.GK_IMG; let _postsCache = null, _postsPromise = null; function loadPosts() { if (_postsCache) return Promise.resolve(_postsCache); if (_postsPromise) return _postsPromise; _postsPromise = (async () => { try { const res = await fetch('assets/posts.json', { cache: 'no-store' }); if (res.ok) { const d = await res.json(); if (d && Array.isArray(d.posts)) { _postsCache = d.posts; return _postsCache; } } } catch (e) { /* fall through */ } if (window.GK_POSTS && Array.isArray(window.GK_POSTS.posts)) { _postsCache = window.GK_POSTS.posts; return _postsCache; } _postsCache = []; return _postsCache; })(); return _postsPromise; } function usePosts() { const initial = _postsCache || (window.GK_POSTS && window.GK_POSTS.posts) || []; const [list, setList] = useState(initial); useEffect(() => { let live = true; loadPosts().then(p => { if (live) setList(p); }); return () => { live = false; }; }, []); return list; } function Starfield({ count = 160, height = 460 }) { let seed = 11; const rnd = () => (seed = (seed * 9301 + 49297) % 233280) / 233280; const shadows = []; for (let i = 0; i < count; i++) shadows.push(`${(rnd() * 100).toFixed(2)}vw ${Math.round(rnd() * height)}px rgba(255,255,255,${(0.25 + rnd() * 0.75).toFixed(2)})`); const big = []; for (let i = 0; i < 6; i++) big.push(`${(rnd() * 100).toFixed(2)}vw ${Math.round(rnd() * height)}px rgba(180,205,255,0.95)`); return ( ); } function PostHero({ post }) { const eyebrow = (post.category || '') ; if (post.night) { return (
{eyebrow}

{post.title}

); } if (post.cover) { return (
{eyebrow}

{post.title}

); } return (
{eyebrow}

{post.title}

); } function NotFound() { return (

Post not found

We couldn't find that article — it may have been moved or removed.

); } function BlogPostContent() { const { openBooking } = useShell(); const posts = usePosts(); const slug = new URLSearchParams(window.location.search).get('post'); const post = posts.find(p => p.slug === slug) || (!slug && posts[0]) || null; useEffect(() => { if (window.lucide) window.lucide.createIcons(); }, [post]); if (posts.length > 0 && !post) return ; if (!post) return
; const related = posts.filter((p) => p.slug !== post.slug).slice(0, 3); return (
{(post.body || []).map((b, i) => ( {b.heading ?

{b.heading}

: null} {b.text ?

{b.text}

: null} {b.items && b.items.length > 0 ?
    {b.items.map((it, j) =>
  • {it}
  • )}
: null}
))}
{related.length > 0 && (
More from the wood

More stories to read

)}
Stay nearby

Come and stay in the wood

The Gamekeeper's Cottage is hidden in its own hundred-acre Suffolk wood, near Southwold — a perfect base for exploring all of this.

Book direct

The Gamekeeper's Cottage

Sleeps 5 · 3 bedrooms · four acres of private woodland

); } window.GKmount('blog-post', BlogPostContent);