> ## Documentation Index
> Fetch the complete documentation index at: https://felimet-hub.jmcores.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Technical notes: AI, CUDA, Python, and writing

> Technical notes on CUDA and cuDNN setup, Conda and Python environment management, and Traditional Chinese technical writing workflows.

export const notesEn = [{
  "title": "Windows CUDA & cuDNN Development Environment Setup Guide",
  "description": "Step-by-step Windows guide for installing NVIDIA drivers, the CUDA Toolkit, and cuDNN: a deep learning environment setup walkthrough with verification steps.",
  "href": "/en/notes/ai-core/environment/cuda-setup",
  "tags": ["CUDA", "NVIDIA", "DL", "EnvSetup"],
  "featured": false,
  "order": 1,
  "date": "2025-03-18",
  "pubType": "",
  "venue": "",
  "confType": "",
  "award": ""
}, {
  "title": "WSL2 CUDA Toolkit Installation Guide",
  "description": "Install the CUDA Toolkit on WSL2 + Ubuntu: system-wide apt vs user-level runfile compared, environment variables, user switching, and troubleshooting, including the no-sudo scenario.",
  "href": "/en/notes/ai-core/environment/wsl-cuda-setup",
  "tags": ["CUDA", "WSL", "NVIDIA", "EnvSetup"],
  "featured": false,
  "order": 2,
  "date": "2026-07-05",
  "pubType": "",
  "venue": "",
  "confType": "",
  "award": ""
}, {
  "title": "Installing Docker on Windows (WSL 2 backend)",
  "description": "The starting point for the Docker notes: install Docker on Windows with WSL 2, then on to commands, configuration, Compose, and Dockerfile.",
  "href": "/en/notes/docker/install-windows",
  "tags": ["Docker", "WSL", "Windows", "Containers"],
  "featured": false,
  "order": 1,
  "date": "2026-06-10",
  "pubType": "",
  "venue": "",
  "confType": "",
  "award": ""
}, {
  "title": "Technical Writing Guide & Document Quality Standards",
  "description": "Technical writing guide covering Traditional Chinese typography, academic style, spacing, punctuation, proper nouns, Word formatting, and AI-assisted review.",
  "href": "/en/notes/knowledge/writing-skills/zhtw-writing",
  "tags": ["Writing", "Documentation", "BestPractice"],
  "featured": false,
  "order": 999,
  "date": "2025-02-13",
  "pubType": "",
  "venue": "",
  "confType": "",
  "award": ""
}, {
  "title": "Synology NAS OpenVPN Server Setup Guide",
  "description": "Set up an OpenVPN server on a DSM 7 Synology NAS using the VPN Server package: accounts and permissions, server settings, DDNS, router port forwarding, firewall, config export, and client connection across platforms.",
  "href": "/en/notes/network/synology-openvpn",
  "tags": ["OpenVPN", "Synology", "VPN", "Networking"],
  "featured": false,
  "order": 999,
  "date": "2025-06-09",
  "pubType": "",
  "venue": "",
  "confType": "",
  "award": ""
}, {
  "title": "Windows 11 Multi-User Remote Desktop (RDP) Setup",
  "description": "Lift the single-session limit on Windows 11 Remote Desktop using RDP Wrapper for concurrent multi-user sessions: install and verify, NLA and session security, router port forwarding, Cloudflare access, and troubleshooting.",
  "href": "/en/notes/network/windows-multi-rdp",
  "tags": ["RDP", "Windows", "Remote Desktop", "Networking"],
  "featured": false,
  "order": 999,
  "date": "2025-06-09",
  "pubType": "",
  "venue": "",
  "confType": "",
  "award": ""
}, {
  "title": "Conda Installation and Configuration Guide",
  "description": "Conda guide covering Anaconda vs. Miniconda, installation, custom paths, channels, and Python environment management for data science workflows.",
  "href": "/en/notes/software/languages/python/conda-guide",
  "tags": ["Python", "Conda", "Miniconda", "Anaconda", "EnvSetup"],
  "featured": false,
  "order": 999,
  "date": "2024-12-06",
  "pubType": "",
  "venue": "",
  "confType": "",
  "award": ""
}, {
  "title": "WSL Ubuntu System Migration Guide",
  "description": "Move a space-hungry WSL Ubuntu off the C drive to another disk: package and redeploy with wsl --export / --import, keeping all software and settings while freeing system-drive space.",
  "href": "/en/notes/software/wsl-ubuntu-migration",
  "tags": ["WSL", "Ubuntu", "Windows", "SysAdmin"],
  "featured": false,
  "order": 999,
  "date": "2025-07-11",
  "pubType": "",
  "venue": "",
  "confType": "",
  "award": ""
}];

export const Gallery = ({items = [], type = "projects", lang = "zh"}) => {
  const TAG_LIMIT = 12;
  const t = lang === "en" ? {
    all: "All",
    more: n => `+${n} more`,
    less: "Show less",
    filter: "Filter",
    unit: n => `${n} items`,
    featured: "Featured first",
    date: "Newest first",
    title: "Title A→Z"
  } : {
    all: "全部",
    more: n => `+${n} 更多`,
    less: "收起",
    filter: "篩選",
    unit: n => `${n} 篇`,
    featured: "精選優先",
    date: "日期新→舊",
    title: "標題 A→Z"
  };
  const toTags = v => Array.isArray(v) ? v : typeof v === "string" && v.trim().startsWith("[") ? (() => {
    try {
      return JSON.parse(v);
    } catch {
      return [];
    }
  })() : v ? [String(v)] : [];
  const tagCount = {};
  for (const it of items) for (const tg of toTags(it.tags)) tagCount[tg] = (tagCount[tg] || 0) + 1;
  const sortedTags = Object.keys(tagCount).sort((a, b) => tagCount[b] - tagCount[a]);
  const [tag, setTag] = useState("all");
  const [sort, setSort] = useState(type === "publications" ? "date" : "featured");
  const [showAllTags, setShowAllTags] = useState(false);
  const visibleTags = showAllTags ? sortedTags : sortedTags.slice(0, TAG_LIMIT);
  const filtered = tag === "all" ? items : items.filter(i => toTags(i.tags).includes(tag));
  const shown = [...filtered].sort((a, b) => {
    if (sort === "title") return a.title.localeCompare(b.title, lang === "en" ? "en" : "zh-TW");
    if (sort === "date") return String(b.date).localeCompare(String(a.date));
    return (b.featured ? 1 : 0) - (a.featured ? 1 : 0) || a.order - b.order;
  });
  return <div>
      <div style={{
    marginBottom: "1.75rem"
  }}>
        <div style={{
    display: "flex",
    justifyContent: "space-between",
    alignItems: "center",
    marginBottom: "0.6rem"
  }}>
          <span className="g-filter-label">{t.filter} · {t.unit(shown.length)}</span>
          <select className="g-sort" value={sort} onChange={e => setSort(e.target.value)}>
            <option value="featured">{t.featured}</option>
            <option value="date">{t.date}</option>
            <option value="title">{t.title}</option>
          </select>
        </div>
        <div style={{
    display: "flex",
    flexWrap: "wrap",
    gap: "0.4rem",
    alignItems: "center"
  }}>
          <button className={"g-chip" + (tag === "all" ? " g-chip-on" : "")} onClick={() => setTag("all")}>{t.all}</button>
          {visibleTags.map(tg => <button key={tg} className={"g-chip" + (tag === tg ? " g-chip-on" : "")} onClick={() => setTag(tg)}>{tg}</button>)}
          {sortedTags.length > TAG_LIMIT && <button className="g-more" onClick={() => setShowAllTags(!showAllTags)}>
              {showAllTags ? t.less : t.more(sortedTags.length - TAG_LIMIT)}
            </button>}
        </div>
      </div>

      <div style={{
    display: "grid",
    gridTemplateColumns: "repeat(auto-fill, minmax(290px, 1fr))",
    gap: "1rem"
  }}>
        {shown.map(i => {
    const tags = toTags(i.tags);
    return <a key={i.href} href={i.href} className="g-card">
              <div className="g-card-title">
                {i.featured && <span style={{
      color: "#bf7551",
      marginRight: "0.3rem"
    }}>★</span>}
                {i.title}
              </div>
              <div className="g-card-desc">
                {i.description.length > 88 ? i.description.slice(0, 88) + "…" : i.description}
              </div>
              {(i.venue || tags.length > 0) && <div className="g-card-meta">
                  {i.venue && <div className="g-card-venue">{i.venue}</div>}
                  <div style={{
      display: "flex",
      flexWrap: "wrap",
      gap: "0.3rem"
    }}>
                    {tags.slice(0, 3).map(tg => <span key={tg} className="g-tag">{tg}</span>)}
                    {tags.length > 3 && <span className="g-tag-more">+{tags.length - 3}</span>}
                  </div>
                </div>}
            </a>;
  })}
      </div>
    </div>;
};

<Gallery items={notesEn} type="notes" lang="en" />
