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

# Hands-On

export const ShowMore = ({children, className = '', id = 'posts', btnClassName = ''}) => {
  const hash = 'show-all-' + id;
  const [expanded, setExpanded] = useState(false);
  useEffect(() => {
    const check = () => {
      if (window.location.hash === '#' + hash) {
        setExpanded(true);
      }
    };
    check();
    window.addEventListener('hashchange', check);
    return () => window.removeEventListener('hashchange', check);
  }, [hash]);
  const wrapClass = expanded ? className : className + ' blog-paginated';
  return <div>
      <div className={wrapClass}>
        {children}
      </div>
      {!expanded && <div className={btnClassName} style={{
    marginTop: '2rem',
    textAlign: 'center'
  }}>
          <a href={'#' + hash} style={{
    display: 'inline-flex',
    alignItems: 'center',
    gap: '0.5rem',
    padding: '0.75rem 1.5rem',
    borderRadius: '9999px',
    border: '1px solid #e5e7eb',
    fontSize: '0.875rem',
    fontWeight: 500,
    color: '#374151',
    textDecoration: 'none'
  }}>
            Show all posts ▾
          </a>
        </div>}
    </div>;
};

<ShowMore id="hands-on-articles" className="blog-card-grid">
  <a href="/posts/use-cases/n8n-upgrade-with-postgresql-and-redis" className="blog-card group rounded-xl bg-card border-theme card-hover shadow-sm hover:shadow-md transition-all overflow-hidden flex flex-col">
    {`/images/posts/use-cases/n8n-upgrade-postgresql-redis/n8n-postgresql-redis-thumbnail.svg` !== '' && (
          <div className="blog-card-img-wrap">
            <img src="/images/posts/use-cases/n8n-upgrade-postgresql-redis/n8n-postgresql-redis-thumbnail.svg" alt="Scale n8n with PostgreSQL and Redis on Upsun" className="blog-card-img" />
          </div>
        )}

    <div className="blog-card-body">
      <div className="flex items-center gap-2">
        {`hands-on` !== '' && (
                      <span className="text-xs font-semibold uppercase tracking-wider px-2 py-0.5 rounded-md bg-accent-badge border border-accent-soft text-accent">
                        hands-on
                      </span>
                    )}

        <span className="text-xs text-subtle">Wednesday, April 29th 2026</span>
      </div>

      <h3 className="blog-card-title group-hover:text-accent transition-colors">Scale n8n with PostgreSQL and Redis on Upsun</h3>
      <p className="blog-card-desc">Upgrade your n8n instance from SQLite to PostgreSQL and add Redis caching for better performance, scalability, and reliability. Step-by-step guide for Upsun.</p>
    </div>
  </a>

  <a href="/posts/hands-on/that-cron-should-be-a-worker" className="blog-card group rounded-xl bg-card border-theme card-hover shadow-sm hover:shadow-md transition-all overflow-hidden flex flex-col">
    {`/images/posts/hands-on/that-cron-should-be-a-worker/that-cron-should-be-a-worker.webp` !== '' && (
          <div className="blog-card-img-wrap">
            <img src="/images/posts/hands-on/that-cron-should-be-a-worker/that-cron-should-be-a-worker.webp" alt="That cron should be a worker" className="blog-card-img" />
          </div>
        )}

    <div className="blog-card-body">
      <div className="flex items-center gap-2">
        {`hands-on` !== '' && (
                      <span className="text-xs font-semibold uppercase tracking-wider px-2 py-0.5 rounded-md bg-accent-badge border border-accent-soft text-accent">
                        hands-on
                      </span>
                    )}

        <span className="text-xs text-subtle">Wednesday, March 4th 2026</span>
      </div>

      <h3 className="blog-card-title group-hover:text-accent transition-colors">That cron should be a worker</h3>
      <p className="blog-card-desc">Long-running crons block your deployments, steal resources from your app container, and create support tickets. Here's when to use workers instead.</p>
    </div>
  </a>

  <a href="/posts/hands-on/the-real-story-of-setting-up-drupal-canvas-with-ai" className="blog-card group rounded-xl bg-card border-theme card-hover shadow-sm hover:shadow-md transition-all overflow-hidden flex flex-col">
    {`/images/posts/hands-on/the-real-story-of-setting-up-drupal-canvas-with-ai/lemberg-setting-up-drupal-canvas-with-ai.webp` !== '' && (
          <div className="blog-card-img-wrap">
            <img src="/images/posts/hands-on/the-real-story-of-setting-up-drupal-canvas-with-ai/lemberg-setting-up-drupal-canvas-with-ai.webp" alt="From DrupalCon keynote to live Upsun demo: the real story of setting up Drupal Canvas with AI" className="blog-card-img" />
          </div>
        )}

    <div className="blog-card-body">
      <div className="flex items-center gap-2">
        {`hands-on` !== '' && (
                      <span className="text-xs font-semibold uppercase tracking-wider px-2 py-0.5 rounded-md bg-accent-badge border border-accent-soft text-accent">
                        hands-on
                      </span>
                    )}

        <span className="text-xs text-subtle">Friday, February 13th 2026</span>
      </div>

      <h3 className="blog-card-title group-hover:text-accent transition-colors">From DrupalCon keynote to live Upsun demo: the real story of setting up Drupal Canvas with AI</h3>
      <p className="blog-card-desc">Discover how the Lemberg Solutions team set up Drupal Canvas with an AI assistant: how long it took, the challenges we faced and lessons we learned.</p>
    </div>
  </a>

  <a href="/posts/hands-on/scriberr-on-upsun" className="blog-card group rounded-xl bg-card border-theme card-hover shadow-sm hover:shadow-md transition-all overflow-hidden flex flex-col">
    {`/images/posts/hands-on/scriberr-on-upsun/scriberr-on-upsun.webp` !== '' && (
          <div className="blog-card-img-wrap">
            <img src="/images/posts/hands-on/scriberr-on-upsun/scriberr-on-upsun.webp" alt="Scriberr on Upsun" className="blog-card-img" />
          </div>
        )}

    <div className="blog-card-body">
      <div className="flex items-center gap-2">
        {`hands-on` !== '' && (
                      <span className="text-xs font-semibold uppercase tracking-wider px-2 py-0.5 rounded-md bg-accent-badge border border-accent-soft text-accent">
                        hands-on
                      </span>
                    )}

        <span className="text-xs text-subtle">Tuesday, February 10th 2026</span>
      </div>

      <h3 className="blog-card-title group-hover:text-accent transition-colors">Scriberr on Upsun</h3>
      <p className="blog-card-desc">Learn how to deploy Scriberr, an AI-powered transcription tool, on Upsun for self-hosted audio and video transcription.</p>
    </div>
  </a>

  <a href="/posts/hands-on/unstable-website-use-queues" className="blog-card group rounded-xl bg-card border-theme card-hover shadow-sm hover:shadow-md transition-all overflow-hidden flex flex-col">
    {`/images/posts/hands-on/unstable-website-use-queues/unstable-website-use-queues.webp` !== '' && (
          <div className="blog-card-img-wrap">
            <img src="/images/posts/hands-on/unstable-website-use-queues/unstable-website-use-queues.webp" alt="Unstable website? Use queues." className="blog-card-img" />
          </div>
        )}

    <div className="blog-card-body">
      <div className="flex items-center gap-2">
        {`hands-on` !== '' && (
                      <span className="text-xs font-semibold uppercase tracking-wider px-2 py-0.5 rounded-md bg-accent-badge border border-accent-soft text-accent">
                        hands-on
                      </span>
                    )}

        <span className="text-xs text-subtle">Thursday, February 5th 2026</span>
      </div>

      <h3 className="blog-card-title group-hover:text-accent transition-colors">Unstable website? Use queues.</h3>
      <p className="blog-card-desc">Your site throws 502 errors when external APIs are slow. The fix isn't more resources. It's offloading that work to background jobs so your responses stay fast.</p>
    </div>
  </a>

  <a href="/posts/hands-on/how-to-use-harlequin-sql-ide-with-upsun" className="blog-card group rounded-xl bg-card border-theme card-hover shadow-sm hover:shadow-md transition-all overflow-hidden flex flex-col">
    {`/images/posts/hands-on/how-to-use-harlequin-sql-ide-with-upsun/harlequin-interface.webp` !== '' && (
          <div className="blog-card-img-wrap">
            <img src="/images/posts/hands-on/how-to-use-harlequin-sql-ide-with-upsun/harlequin-interface.webp" alt="How to Use Harlequin SQL IDE with Upsun" className="blog-card-img" />
          </div>
        )}

    <div className="blog-card-body">
      <div className="flex items-center gap-2">
        {`hands-on` !== '' && (
                      <span className="text-xs font-semibold uppercase tracking-wider px-2 py-0.5 rounded-md bg-accent-badge border border-accent-soft text-accent">
                        hands-on
                      </span>
                    )}

        <span className="text-xs text-subtle">Wednesday, January 14th 2026</span>
      </div>

      <h3 className="blog-card-title group-hover:text-accent transition-colors">How to Use Harlequin SQL IDE with Upsun</h3>
      <p className="blog-card-desc">Learn two ways to connect Harlequin SQL IDE to your Upsun PostgreSQL database: using local SSH tunnels or deploying Harlequin directly on the platform.</p>
    </div>
  </a>

  <a href="/posts/hands-on/stop-testing-jcr-apps-in-production" className="blog-card group rounded-xl bg-card border-theme card-hover shadow-sm hover:shadow-md transition-all overflow-hidden flex flex-col">
    {`/images/posts/hands-on/stop-testing-jcr-apps-in-production/stop-testing-jcr-apps-in-production.webp` !== '' && (
          <div className="blog-card-img-wrap">
            <img src="/images/posts/hands-on/stop-testing-jcr-apps-in-production/stop-testing-jcr-apps-in-production.webp" alt="Stop testing JCR apps in production" className="blog-card-img" />
          </div>
        )}

    <div className="blog-card-body">
      <div className="flex items-center gap-2">
        {`hands-on` !== '' && (
                      <span className="text-xs font-semibold uppercase tracking-wider px-2 py-0.5 rounded-md bg-accent-badge border border-accent-soft text-accent">
                        hands-on
                      </span>
                    )}

        <span className="text-xs text-subtle">Tuesday, January 6th 2026</span>
      </div>

      <h3 className="blog-card-title group-hover:text-accent transition-colors">Stop testing JCR apps in production</h3>
      <p className="blog-card-desc">Learn why JCR-based applications benefit from fast, production-grade environment cloning. Discover how Upsun removes one of JCR's biggest operational challenges through instant repository duplication.</p>
    </div>
  </a>

  <a href="/posts/hands-on/civicrm-drupal-11-on-upsun" className="blog-card group rounded-xl bg-card border-theme card-hover shadow-sm hover:shadow-md transition-all overflow-hidden flex flex-col">
    {`/images/posts/hands-on/civicrm-drupal-11-on-upsun/UpsunxSkvare-800x300.webp` !== '' && (
          <div className="blog-card-img-wrap">
            <img src="/images/posts/hands-on/civicrm-drupal-11-on-upsun/UpsunxSkvare-800x300.webp" alt="Installing CiviCRM with Drupal 11 on Upsun" className="blog-card-img" />
          </div>
        )}

    <div className="blog-card-body">
      <div className="flex items-center gap-2">
        {`hands-on` !== '' && (
                      <span className="text-xs font-semibold uppercase tracking-wider px-2 py-0.5 rounded-md bg-accent-badge border border-accent-soft text-accent">
                        hands-on
                      </span>
                    )}

        <span className="text-xs text-subtle">Friday, December 19th 2025</span>
      </div>

      <h3 className="blog-card-title group-hover:text-accent transition-colors">Installing CiviCRM with Drupal 11 on Upsun</h3>
      <p className="blog-card-desc">Learn how to install CiviCRM with Drupal 11 on Upsun, from config.yml and databases to cron, caching, extensions and Skvare’s best-practice template.</p>
    </div>
  </a>

  <a href="/posts/hands-on/migration-day-executing-your-upsun-cutover" className="blog-card group rounded-xl bg-card border-theme card-hover shadow-sm hover:shadow-md transition-all overflow-hidden flex flex-col">
    {`/images/posts/hands-on/migration-day-executing-your-upsun-cutover/migration-day-executing-your-upsun-cutover.webp` !== '' && (
          <div className="blog-card-img-wrap">
            <img src="/images/posts/hands-on/migration-day-executing-your-upsun-cutover/migration-day-executing-your-upsun-cutover.webp" alt="Migration day: executing your Upsun cutover" className="blog-card-img" />
          </div>
        )}

    <div className="blog-card-body">
      <div className="flex items-center gap-2">
        {`hands-on` !== '' && (
                      <span className="text-xs font-semibold uppercase tracking-wider px-2 py-0.5 rounded-md bg-accent-badge border border-accent-soft text-accent">
                        hands-on
                      </span>
                    )}

        <span className="text-xs text-subtle">Tuesday, December 16th 2025</span>
      </div>

      <h3 className="blog-card-title group-hover:text-accent transition-colors">Migration day: executing your Upsun cutover</h3>
      <p className="blog-card-desc">A step-by-step guide to migration day: maintenance windows, cutover sequences, verification, and post-migration monitoring strategies.</p>
    </div>
  </a>

  <a href="/posts/hands-on/zero-downtime-deployments-with-upsun" className="blog-card group rounded-xl bg-card border-theme card-hover shadow-sm hover:shadow-md transition-all overflow-hidden flex flex-col">
    {`/images/posts/hands-on/zero-downtime-deployments-with-upsun/ZZD-dev-center.webp` !== '' && (
          <div className="blog-card-img-wrap">
            <img src="/images/posts/hands-on/zero-downtime-deployments-with-upsun/ZZD-dev-center.webp" alt="Zero-downtime deployments: now in open beta" className="blog-card-img" />
          </div>
        )}

    <div className="blog-card-body">
      <div className="flex items-center gap-2">
        {`hands-on` !== '' && (
                      <span className="text-xs font-semibold uppercase tracking-wider px-2 py-0.5 rounded-md bg-accent-badge border border-accent-soft text-accent">
                        hands-on
                      </span>
                    )}

        <span className="text-xs text-subtle">Wednesday, December 3rd 2025</span>
      </div>

      <h3 className="blog-card-title group-hover:text-accent transition-colors">Zero-downtime deployments: now in open beta</h3>
      <p className="blog-card-desc">We've launched zero-downtime deployments in open beta. Deploy your applications without service interruption.</p>
    </div>
  </a>

  <a href="/posts/hands-on/ai-use-case-generate-load-test-scenarios" className="blog-card group rounded-xl bg-card border-theme card-hover shadow-sm hover:shadow-md transition-all overflow-hidden flex flex-col">
    {`/images/posts/hands-on/ai-use-case-generate-load-test-scenarios/ai-use-case-generate-load-test-scenarios.webp` !== '' && (
          <div className="blog-card-img-wrap">
            <img src="/images/posts/hands-on/ai-use-case-generate-load-test-scenarios/ai-use-case-generate-load-test-scenarios.webp" alt="AI use-case: Generate load test scenarios with MCPs" className="blog-card-img" />
          </div>
        )}

    <div className="blog-card-body">
      <div className="flex items-center gap-2">
        {`hands-on` !== '' && (
                      <span className="text-xs font-semibold uppercase tracking-wider px-2 py-0.5 rounded-md bg-accent-badge border border-accent-soft text-accent">
                        hands-on
                      </span>
                    )}

        <span className="text-xs text-subtle">Thursday, November 27th 2025</span>
      </div>

      <h3 className="blog-card-title group-hover:text-accent transition-colors">AI use-case: Generate load test scenarios with MCPs</h3>
      <p className="blog-card-desc">Automate Locust load testing by combining Chrome MCP and Context7 to generate realistic user behavior patterns with Claude Code.</p>
    </div>
  </a>

  <a href="/posts/hands-on/varnish-104-advanced-traffic-filtering-with-classification-headers-on-upsun" className="blog-card group rounded-xl bg-card border-theme card-hover shadow-sm hover:shadow-md transition-all overflow-hidden flex flex-col">
    {`/images/posts/hands-on/varnish-104-advanced-traffic-filtering-with-classification-headers-on-upsun/varnish-104.webp` !== '' && (
          <div className="blog-card-img-wrap">
            <img src="/images/posts/hands-on/varnish-104-advanced-traffic-filtering-with-classification-headers-on-upsun/varnish-104.webp" alt="Varnish 104: Advanced Traffic Filtering with Classification Headers on Upsun" className="blog-card-img" />
          </div>
        )}

    <div className="blog-card-body">
      <div className="flex items-center gap-2">
        {`hands-on` !== '' && (
                      <span className="text-xs font-semibold uppercase tracking-wider px-2 py-0.5 rounded-md bg-accent-badge border border-accent-soft text-accent">
                        hands-on
                      </span>
                    )}

        <span className="text-xs text-subtle">Friday, November 7th 2025</span>
      </div>

      <h3 className="blog-card-title group-hover:text-accent transition-colors">Varnish 104: Advanced Traffic Filtering with Classification Headers on Upsun</h3>
      <p className="blog-card-desc">Learn how to implement advanced security controls in Varnish on Upsun using classification headers to block malicious traffic, restrict geographic access, filter by ASN, and protect sensitive paths with HTTP Basic Auth.</p>
    </div>
  </a>

  <a href="/posts/hands-on/varnish-103-cache-optimization-with-url-normalization-on-upsun" className="blog-card group rounded-xl bg-card border-theme card-hover shadow-sm hover:shadow-md transition-all overflow-hidden flex flex-col">
    {`/images/posts/hands-on/varnish-103-cache-optimization-with-url-normalization-on-upsun/varnish-103.webp` !== '' && (
          <div className="blog-card-img-wrap">
            <img src="/images/posts/hands-on/varnish-103-cache-optimization-with-url-normalization-on-upsun/varnish-103.webp" alt="Varnish 103: Cache Optimization with URL Normalization on Upsun" className="blog-card-img" />
          </div>
        )}

    <div className="blog-card-body">
      <div className="flex items-center gap-2">
        {`hands-on` !== '' && (
                      <span className="text-xs font-semibold uppercase tracking-wider px-2 py-0.5 rounded-md bg-accent-badge border border-accent-soft text-accent">
                        hands-on
                      </span>
                    )}

        <span className="text-xs text-subtle">Friday, October 31st 2025</span>
      </div>

      <h3 className="blog-card-title group-hover:text-accent transition-colors">Varnish 103: Cache Optimization with URL Normalization on Upsun</h3>
      <p className="blog-card-desc">Learn how to maximize Varnish cache efficiency through URL normalization, query string sorting, and tracking parameter removal to dramatically improve cache hit ratios and reduce backend load.</p>
    </div>
  </a>

  <a href="/posts/hands-on/varnish-102-protecting-your-application-with-rate-limiting-on-upsun" className="blog-card group rounded-xl bg-card border-theme card-hover shadow-sm hover:shadow-md transition-all overflow-hidden flex flex-col">
    {`/images/posts/hands-on/varnish-102-protecting-your-application-with-rate-limiting-on-upsun/varnish-102.webp` !== '' && (
          <div className="blog-card-img-wrap">
            <img src="/images/posts/hands-on/varnish-102-protecting-your-application-with-rate-limiting-on-upsun/varnish-102.webp" alt="Varnish 102: Protecting Your Application with Rate Limiting on Upsun" className="blog-card-img" />
          </div>
        )}

    <div className="blog-card-body">
      <div className="flex items-center gap-2">
        {`hands-on` !== '' && (
                      <span className="text-xs font-semibold uppercase tracking-wider px-2 py-0.5 rounded-md bg-accent-badge border border-accent-soft text-accent">
                        hands-on
                      </span>
                    )}

        <span className="text-xs text-subtle">Friday, October 24th 2025</span>
      </div>

      <h3 className="blog-card-title group-hover:text-accent transition-colors">Varnish 102: Protecting Your Application with Rate Limiting on Upsun</h3>
      <p className="blog-card-desc">Learn how to implement effective rate limiting in Varnish using the vsthrottle VMOD to protect your application from abuse, prevent DDoS attacks, and ensure fair resource allocation.</p>
    </div>
  </a>

  <a href="/posts/hands-on/varnish-101-protecting-paths-with-http-basic-authentication-on-upsun" className="blog-card group rounded-xl bg-card border-theme card-hover shadow-sm hover:shadow-md transition-all overflow-hidden flex flex-col">
    {`/images/posts/hands-on/varnish-101-protecting-paths-with-http-basic-authentication-on-upsun/varnish-101.webp` !== '' && (
          <div className="blog-card-img-wrap">
            <img src="/images/posts/hands-on/varnish-101-protecting-paths-with-http-basic-authentication-on-upsun/varnish-101.webp" alt="Varnish 101: Protecting Paths with HTTP Basic Authentication on Upsun" className="blog-card-img" />
          </div>
        )}

    <div className="blog-card-body">
      <div className="flex items-center gap-2">
        {`hands-on` !== '' && (
                      <span className="text-xs font-semibold uppercase tracking-wider px-2 py-0.5 rounded-md bg-accent-badge border border-accent-soft text-accent">
                        hands-on
                      </span>
                    )}

        <span className="text-xs text-subtle">Friday, October 17th 2025</span>
      </div>

      <h3 className="blog-card-title group-hover:text-accent transition-colors">Varnish 101: Protecting Paths with HTTP Basic Authentication on Upsun</h3>
      <p className="blog-card-desc">Learn how to implement HTTP Basic Authentication directly in Varnish VCL on Upsun to protect specific paths like admin areas, staging environments, and work-in-progress content without touching your backend.</p>
    </div>
  </a>

  <a href="/posts/hands-on/building-internal-ai-agents-for-our-teams-on-upsun" className="blog-card group rounded-xl bg-card border-theme card-hover shadow-sm hover:shadow-md transition-all overflow-hidden flex flex-col">
    {`/images/posts/hands-on/building-internal-ai-agents-for-our-teams-on-upsun/building-internal-ai-agents-for-our-teams-on-upsun.webp` !== '' && (
          <div className="blog-card-img-wrap">
            <img src="/images/posts/hands-on/building-internal-ai-agents-for-our-teams-on-upsun/building-internal-ai-agents-for-our-teams-on-upsun.webp" alt="Building internal AI agents for our teams on Upsun" className="blog-card-img" />
          </div>
        )}

    <div className="blog-card-body">
      <div className="flex items-center gap-2">
        {`hands-on` !== '' && (
                      <span className="text-xs font-semibold uppercase tracking-wider px-2 py-0.5 rounded-md bg-accent-badge border border-accent-soft text-accent">
                        hands-on
                      </span>
                    )}

        <span className="text-xs text-subtle">Tuesday, September 30th 2025</span>
      </div>

      <h3 className="blog-card-title group-hover:text-accent transition-colors">Building internal AI agents for our teams on Upsun</h3>
      <p className="blog-card-desc">Learn how to build and deploy production-ready AI agents on Upsun using Google's ADK, ChromaDB vector database, and Retrieval-Augmented Generation (RAG) to create context-aware, domain-specific agents for your team.</p>
    </div>
  </a>

  <a href="/posts/hands-on/run-tailscale-on-upsun-secure-vpn-connections" className="blog-card group rounded-xl bg-card border-theme card-hover shadow-sm hover:shadow-md transition-all overflow-hidden flex flex-col">
    {`/images/posts/hands-on/run-tailscale-on-upsun-secure-vpn-connections/run-tailscale-on-upsun-secure-vpn-connections.webp` !== '' && (
          <div className="blog-card-img-wrap">
            <img src="/images/posts/hands-on/run-tailscale-on-upsun-secure-vpn-connections/run-tailscale-on-upsun-secure-vpn-connections.webp" alt="Run Tailscale on Upsun: Create secure VPN connections for your applications" className="blog-card-img" />
          </div>
        )}

    <div className="blog-card-body">
      <div className="flex items-center gap-2">
        {`hands-on` !== '' && (
                      <span className="text-xs font-semibold uppercase tracking-wider px-2 py-0.5 rounded-md bg-accent-badge border border-accent-soft text-accent">
                        hands-on
                      </span>
                    )}

        <span className="text-xs text-subtle">Tuesday, September 16th 2025</span>
      </div>

      <h3 className="blog-card-title group-hover:text-accent transition-colors">Run Tailscale on Upsun: Create secure VPN connections for your applications</h3>
      <p className="blog-card-desc">Learn how to integrate Tailscale VPN with your Upsun applications to create secure, private network connections between your containers and infrastructure.</p>
    </div>
  </a>

  <a href="/posts/hands-on/store-embeddings-in-chroma-with-persistent-storage-nodejs-and-python-examples" className="blog-card group rounded-xl bg-card border-theme card-hover shadow-sm hover:shadow-md transition-all overflow-hidden flex flex-col">
    {`/images/posts/hands-on/store-embeddings-in-chroma-with-persistent-storage-nodejs-and-python-examples/thumbnail.webp` !== '' && (
          <div className="blog-card-img-wrap">
            <img src="/images/posts/hands-on/store-embeddings-in-chroma-with-persistent-storage-nodejs-and-python-examples/thumbnail.webp" alt="Store embeddings in chroma with persistent storage (nodejs and python examples)" className="blog-card-img" />
          </div>
        )}

    <div className="blog-card-body">
      <div className="flex items-center gap-2">
        {`hands-on` !== '' && (
                      <span className="text-xs font-semibold uppercase tracking-wider px-2 py-0.5 rounded-md bg-accent-badge border border-accent-soft text-accent">
                        hands-on
                      </span>
                    )}

        <span className="text-xs text-subtle">Wednesday, September 3rd 2025</span>
      </div>

      <h3 className="blog-card-title group-hover:text-accent transition-colors">Store embeddings in chroma with persistent storage (nodejs and python examples)</h3>
      <p className="blog-card-desc">Learn how to implement Chroma with persistent storage on Upsun using both Node.js and Python, including document ingestion and embedding storage.</p>
    </div>
  </a>

  <a href="/posts/hands-on/fastly-maintenance" className="blog-card group rounded-xl bg-card border-theme card-hover shadow-sm hover:shadow-md transition-all overflow-hidden flex flex-col">
    {`/images/posts/hands-on/fastly-maintenance/manualjob.webp` !== '' && (
          <div className="blog-card-img-wrap">
            <img src="/images/posts/hands-on/fastly-maintenance/manualjob.webp" alt="How to enable custom maintenance page in Fastly" className="blog-card-img" />
          </div>
        )}

    <div className="blog-card-body">
      <div className="flex items-center gap-2">
        {`hands-on` !== '' && (
                      <span className="text-xs font-semibold uppercase tracking-wider px-2 py-0.5 rounded-md bg-accent-badge border border-accent-soft text-accent">
                        hands-on
                      </span>
                    )}

        <span className="text-xs text-subtle">Monday, August 25th 2025</span>
      </div>

      <h3 className="blog-card-title group-hover:text-accent transition-colors">How to enable custom maintenance page in Fastly</h3>
      <p className="blog-card-desc">Configure GitLab CI/CD to deploy to Upsun from private air-gapped GitLab instances using push-based workflows and API automation.</p>
    </div>
  </a>

  <a href="/posts/hands-on/connect-multiple-projects-applications-or-services-together" className="blog-card group rounded-xl bg-card border-theme card-hover shadow-sm hover:shadow-md transition-all overflow-hidden flex flex-col">
    {`/images/posts/hands-on/connect-multiple-projects-applications-or-services-together/connect-multiple-projects-applications-or-services-together.webp` !== '' && (
          <div className="blog-card-img-wrap">
            <img src="/images/posts/hands-on/connect-multiple-projects-applications-or-services-together/connect-multiple-projects-applications-or-services-together.webp" alt="Connect multiple projects applications or services together" className="blog-card-img" />
          </div>
        )}

    <div className="blog-card-body">
      <div className="flex items-center gap-2">
        {`hands-on` !== '' && (
                      <span className="text-xs font-semibold uppercase tracking-wider px-2 py-0.5 rounded-md bg-accent-badge border border-accent-soft text-accent">
                        hands-on
                      </span>
                    )}

        <span className="text-xs text-subtle">Friday, August 15th 2025</span>
      </div>

      <h3 className="blog-card-title group-hover:text-accent transition-colors">Connect multiple projects applications or services together</h3>
      <p className="blog-card-desc">Learn how to use Chisel to securely connect applications and services across different Upsun projects, with a practical MariaDB replication example.</p>
    </div>
  </a>

  <a href="/posts/hands-on/gitlab-push-solution" className="blog-card group rounded-xl bg-card border-theme card-hover shadow-sm hover:shadow-md transition-all overflow-hidden flex flex-col">
    {`/images/posts/hands-on/gitlab-push-solution/manualjob.webp` !== '' && (
          <div className="blog-card-img-wrap">
            <img src="/images/posts/hands-on/gitlab-push-solution/manualjob.webp" alt="Synchronize your air-gapped GitLab with Upsun" className="blog-card-img" />
          </div>
        )}

    <div className="blog-card-body">
      <div className="flex items-center gap-2">
        {`hands-on` !== '' && (
                      <span className="text-xs font-semibold uppercase tracking-wider px-2 py-0.5 rounded-md bg-accent-badge border border-accent-soft text-accent">
                        hands-on
                      </span>
                    )}

        <span className="text-xs text-subtle">Monday, July 21st 2025</span>
      </div>

      <h3 className="blog-card-title group-hover:text-accent transition-colors">Synchronize your air-gapped GitLab with Upsun</h3>
      <p className="blog-card-desc">Configure GitLab CI/CD to deploy to Upsun from private air-gapped GitLab instances using push-based workflows and API automation</p>
    </div>
  </a>

  <a href="/posts/hands-on/deploy-mcp-servers-on-upsun" className="blog-card group rounded-xl bg-card border-theme card-hover shadow-sm hover:shadow-md transition-all overflow-hidden flex flex-col">
    {`/images/posts/hands-on/deploy-mcp-servers-on-upsun/deploy-mcp-servers-on-upsun.webp` !== '' && (
          <div className="blog-card-img-wrap">
            <img src="/images/posts/hands-on/deploy-mcp-servers-on-upsun/deploy-mcp-servers-on-upsun.webp" alt="Build and deploy AI-Native Applications with MCP Servers on Upsun" className="blog-card-img" />
          </div>
        )}

    <div className="blog-card-body">
      <div className="flex items-center gap-2">
        {`hands-on` !== '' && (
                      <span className="text-xs font-semibold uppercase tracking-wider px-2 py-0.5 rounded-md bg-accent-badge border border-accent-soft text-accent">
                        hands-on
                      </span>
                    )}

        <span className="text-xs text-subtle">Thursday, June 5th 2025</span>
      </div>

      <h3 className="blog-card-title group-hover:text-accent transition-colors">Build and deploy AI-Native Applications with MCP Servers on Upsun</h3>
      <p className="blog-card-desc">Learn how Model Context Protocol servers work with different transports and deploy them to Upsun for scalable AI-powered applications</p>
    </div>
  </a>

  <a href="/posts/hands-on/nocode-n8n" className="blog-card group rounded-xl bg-card border-theme card-hover shadow-sm hover:shadow-md transition-all overflow-hidden flex flex-col">
    {`/images/posts/hands-on/nocode-n8n/nocode-n8n-thumbnail.webp` !== '' && (
          <div className="blog-card-img-wrap">
            <img src="/images/posts/hands-on/nocode-n8n/nocode-n8n-thumbnail.webp" alt="NoCode with Upsun: Supercharge Your Automation with Zero Code" className="blog-card-img" />
          </div>
        )}

    <div className="blog-card-body">
      <div className="flex items-center gap-2">
        {`hands-on` !== '' && (
                      <span className="text-xs font-semibold uppercase tracking-wider px-2 py-0.5 rounded-md bg-accent-badge border border-accent-soft text-accent">
                        hands-on
                      </span>
                    )}

        <span className="text-xs text-subtle">Wednesday, May 14th 2025</span>
      </div>

      <h3 className="blog-card-title group-hover:text-accent transition-colors">NoCode with Upsun: Supercharge Your Automation with Zero Code</h3>
      <p className="blog-card-desc">Learn how to leverage Upsun to deploy powerful NoCode tools like n8n for workflow automation. Fast setup, secure hosting, and real-world use cases — all without writing code.</p>
    </div>
  </a>

  <a href="/posts/hands-on/pytorch-running-on-upsun" className="blog-card group rounded-xl bg-card border-theme card-hover shadow-sm hover:shadow-md transition-all overflow-hidden flex flex-col">
    {`/images/posts/hands-on/pytorch-running-on-upsun/pytorch.webp` !== '' && (
          <div className="blog-card-img-wrap">
            <img src="/images/posts/hands-on/pytorch-running-on-upsun/pytorch.webp" alt="How to run PyTorch in an Upsun application?" className="blog-card-img" />
          </div>
        )}

    <div className="blog-card-body">
      <div className="flex items-center gap-2">
        {`hands-on` !== '' && (
                      <span className="text-xs font-semibold uppercase tracking-wider px-2 py-0.5 rounded-md bg-accent-badge border border-accent-soft text-accent">
                        hands-on
                      </span>
                    )}

        <span className="text-xs text-subtle">Thursday, May 1st 2025</span>
      </div>

      <h3 className="blog-card-title group-hover:text-accent transition-colors">How to run PyTorch in an Upsun application?</h3>
      <p className="blog-card-desc">Learn how to deploy a sentiment analysis application powered by PyTorch and FastAPI on the Upsun cloud platform</p>
    </div>
  </a>

  <a href="/posts/hands-on/postgres-mcp-on-upsun" className="blog-card group rounded-xl bg-card border-theme card-hover shadow-sm hover:shadow-md transition-all overflow-hidden flex flex-col">
    {`/images/posts/hands-on/postgres-mcp-on-upsun/postgres-mcp-on-upsun.webp` !== '' && (
          <div className="blog-card-img-wrap">
            <img src="/images/posts/hands-on/postgres-mcp-on-upsun/postgres-mcp-on-upsun.webp" alt="Using PostgreSQL MCP with Upsun Remote Database" className="blog-card-img" />
          </div>
        )}

    <div className="blog-card-body">
      <div className="flex items-center gap-2">
        {`hands-on` !== '' && (
                      <span className="text-xs font-semibold uppercase tracking-wider px-2 py-0.5 rounded-md bg-accent-badge border border-accent-soft text-accent">
                        hands-on
                      </span>
                    )}

        <span className="text-xs text-subtle">Wednesday, April 30th 2025</span>
      </div>

      <h3 className="blog-card-title group-hover:text-accent transition-colors">Using PostgreSQL MCP with Upsun Remote Database</h3>
      <p className="blog-card-desc">Learn how to set up an MCP server to connect your Upsun PostgreSQL database to language models like Claude or IDE like VSCode GitHub Copilot and Cursor, enabling natural language data queries without writing SQL.</p>
    </div>
  </a>

  <a href="/posts/hands-on/route-ids-env" className="blog-card group rounded-xl bg-card border-theme card-hover shadow-sm hover:shadow-md transition-all overflow-hidden flex flex-col">
    {`/images/posts/hands-on/route-ids-env/route-ids-env.webp` !== '' && (
          <div className="blog-card-img-wrap">
            <img src="/images/posts/hands-on/route-ids-env/route-ids-env.webp" alt="How to automatically inject multi-app endpoints as environment variables" className="blog-card-img" />
          </div>
        )}

    <div className="blog-card-body">
      <div className="flex items-center gap-2">
        {`hands-on` !== '' && (
                      <span className="text-xs font-semibold uppercase tracking-wider px-2 py-0.5 rounded-md bg-accent-badge border border-accent-soft text-accent">
                        hands-on
                      </span>
                    )}

        <span className="text-xs text-subtle">Monday, April 28th 2025</span>
      </div>

      <h3 className="blog-card-title group-hover:text-accent transition-colors">How to automatically inject multi-app endpoints as environment variables</h3>
      <p className="blog-card-desc">Learn how to use Upsun route identifiers and the PLATFORM\_ROUTES variable to easily get and use the hostnames of dynamically deployed applications in your project.</p>
    </div>
  </a>

  <a href="/posts/hands-on/install-gh-asset-on-upsun" className="blog-card group rounded-xl bg-card border-theme card-hover shadow-sm hover:shadow-md transition-all overflow-hidden flex flex-col">
    {`/images/posts/hands-on/install-gh-asset-on-upsun/github.webp` !== '' && (
          <div className="blog-card-img-wrap">
            <img src="/images/posts/hands-on/install-gh-asset-on-upsun/github.webp" alt="Up(sun) and ready with GitHub release assets installation" className="blog-card-img" />
          </div>
        )}

    <div className="blog-card-body">
      <div className="flex items-center gap-2">
        {`hands-on` !== '' && (
                      <span className="text-xs font-semibold uppercase tracking-wider px-2 py-0.5 rounded-md bg-accent-badge border border-accent-soft text-accent">
                        hands-on
                      </span>
                    )}

        <span className="text-xs text-subtle">Thursday, April 10th 2025</span>
      </div>

      <h3 className="blog-card-title group-hover:text-accent transition-colors">Up(sun) and ready with GitHub release assets installation</h3>
      <p className="blog-card-desc">Discover how to install any GitHub release asset you want in your Upsun project.</p>
    </div>
  </a>

  <a href="/posts/hands-on/deploying-chainlit-with-rag" className="blog-card group rounded-xl bg-card border-theme card-hover shadow-sm hover:shadow-md transition-all overflow-hidden flex flex-col">
    {`/images/posts/hands-on/deploying-chainlit-with-rag/chainlit-thumbnail.webp` !== '' && (
          <div className="blog-card-img-wrap">
            <img src="/images/posts/hands-on/deploying-chainlit-with-rag/chainlit-thumbnail.webp" alt="Experiment with Chainlit AI interface with RAG on Upsun" className="blog-card-img" />
          </div>
        )}

    <div className="blog-card-body">
      <div className="flex items-center gap-2">
        {`hands-on` !== '' && (
                      <span className="text-xs font-semibold uppercase tracking-wider px-2 py-0.5 rounded-md bg-accent-badge border border-accent-soft text-accent">
                        hands-on
                      </span>
                    )}

        <span className="text-xs text-subtle">Tuesday, January 14th 2025</span>
      </div>

      <h3 className="blog-card-title group-hover:text-accent transition-colors">Experiment with Chainlit AI interface with RAG on Upsun</h3>
      <p className="blog-card-desc">Learn to deploy production-ready RAG applications with Chainlit and Python on Upsun. Tutorial covers OpenAI Assistants integration, llama\_index implementation, and secure authentication.</p>
    </div>
  </a>

  <a href="/posts/hands-on/harnessing-power-embeddings" className="blog-card group rounded-xl bg-card border-theme card-hover shadow-sm hover:shadow-md transition-all overflow-hidden flex flex-col">
    {`/images/posts/devcenter.webp` !== '' && (
          <div className="blog-card-img-wrap">
            <img src="/images/posts/devcenter.webp" alt="Harnessing the power of Embeddings: a real-world example of a watch recommendation app using a vector database." className="blog-card-img" />
          </div>
        )}

    <div className="blog-card-body">
      <div className="flex items-center gap-2">
        {`hands-on` !== '' && (
                      <span className="text-xs font-semibold uppercase tracking-wider px-2 py-0.5 rounded-md bg-accent-badge border border-accent-soft text-accent">
                        hands-on
                      </span>
                    )}

        <span className="text-xs text-subtle">Monday, May 20th 2024</span>
      </div>

      <h3 className="blog-card-title group-hover:text-accent transition-colors">Harnessing the power of Embeddings: a real-world example of a watch recommendation app using a vector database.</h3>
      <p className="blog-card-desc">Learn how to build a real-world watch recommendation application using embeddings and a vector database. This tutorial covers using Postgres with pgvector, Laravel, React, OpenAI, and Groq, deployed on Upsun.</p>
    </div>
  </a>

  <a href="/posts/hands-on/guide-to-limit-deployments-to-platformsh-only-with-tags-part-three" className="blog-card group rounded-xl bg-card border-theme card-hover shadow-sm hover:shadow-md transition-all overflow-hidden flex flex-col">
    {`/images/posts/hands-on/guide-to-limit-deployments-to-platformsh-only-with-tags-part-three/Limit_deployments_to_psh-three.webp` !== '' && (
          <div className="blog-card-img-wrap">
            <img src="/images/posts/hands-on/guide-to-limit-deployments-to-platformsh-only-with-tags-part-three/Limit_deployments_to_psh-three.webp" alt="Limit deployments to Platform.sh only with tags: part three" className="blog-card-img" />
          </div>
        )}

    <div className="blog-card-body">
      <div className="flex items-center gap-2">
        {`hands-on` !== '' && (
                      <span className="text-xs font-semibold uppercase tracking-wider px-2 py-0.5 rounded-md bg-accent-badge border border-accent-soft text-accent">
                        hands-on
                      </span>
                    )}

        <span className="text-xs text-subtle">Friday, April 12th 2024</span>
      </div>

      <h3 className="blog-card-title group-hover:text-accent transition-colors">Limit deployments to Platform.sh only with tags: part three</h3>
      <p className="blog-card-desc">In parts [one](/posts/hands-on/guide-to-limit-deployments-to-platformsh-only-with-tags-part-one) and</p>
    </div>
  </a>

  <a href="/posts/hands-on/guide-to-limit-deployments-to-platformsh-only-with-tags-part-one" className="blog-card group rounded-xl bg-card border-theme card-hover shadow-sm hover:shadow-md transition-all overflow-hidden flex flex-col">
    {`/images/posts/hands-on/guide-to-limit-deployments-to-platformsh-only-with-tags-part-one/Limit_deployments_to_psh-one.webp` !== '' && (
          <div className="blog-card-img-wrap">
            <img src="/images/posts/hands-on/guide-to-limit-deployments-to-platformsh-only-with-tags-part-one/Limit_deployments_to_psh-one.webp" alt="Limit deployments to Platform.sh only with tags: part one" className="blog-card-img" />
          </div>
        )}

    <div className="blog-card-body">
      <div className="flex items-center gap-2">
        {`hands-on` !== '' && (
                      <span className="text-xs font-semibold uppercase tracking-wider px-2 py-0.5 rounded-md bg-accent-badge border border-accent-soft text-accent">
                        hands-on
                      </span>
                    )}

        <span className="text-xs text-subtle">Thursday, March 14th 2024</span>
      </div>

      <h3 className="blog-card-title group-hover:text-accent transition-colors">Limit deployments to Platform.sh only with tags: part one</h3>
      <p className="blog-card-desc">Throughout the years, many users have asked us if it’s possible to only deploy to Platform.sh when a tag is pushed using</p>
    </div>
  </a>

  <a href="/posts/hands-on/guide-to-limit-deployments-to-platformsh-only-with-tags-part-two" className="blog-card group rounded-xl bg-card border-theme card-hover shadow-sm hover:shadow-md transition-all overflow-hidden flex flex-col">
    {`/images/posts/hands-on/guide-to-limit-deployments-to-platformsh-only-with-tags-part-two/Limit_deployments_to_psh-two.webp` !== '' && (
          <div className="blog-card-img-wrap">
            <img src="/images/posts/hands-on/guide-to-limit-deployments-to-platformsh-only-with-tags-part-two/Limit_deployments_to_psh-two.webp" alt="Limit deployments to Platform.sh only when Git tagged: part two" className="blog-card-img" />
          </div>
        )}

    <div className="blog-card-body">
      <div className="flex items-center gap-2">
        {`hands-on` !== '' && (
                      <span className="text-xs font-semibold uppercase tracking-wider px-2 py-0.5 rounded-md bg-accent-badge border border-accent-soft text-accent">
                        hands-on
                      </span>
                    )}

        <span className="text-xs text-subtle">Thursday, March 14th 2024</span>
      </div>

      <h3 className="blog-card-title group-hover:text-accent transition-colors">Limit deployments to Platform.sh only when Git tagged: part two</h3>
      <p className="blog-card-desc">In [part one of this series](https://platform.sh/blog/guide-to-limit-deployments-to-platformsh-only-with-tags-part-one/),</p>
    </div>
  </a>

  <a href="/posts/hands-on/powerup-your-local-development-with-ddev" className="blog-card group rounded-xl bg-card border-theme card-hover shadow-sm hover:shadow-md transition-all overflow-hidden flex flex-col">
    {`/images/posts/hands-on/powerup-your-local-development-with-ddev/Power_ddev_blog.webp` !== '' && (
          <div className="blog-card-img-wrap">
            <img src="/images/posts/hands-on/powerup-your-local-development-with-ddev/Power_ddev_blog.webp" alt="Power-up Your Local Development with DDEV" className="blog-card-img" />
          </div>
        )}

    <div className="blog-card-body">
      <div className="flex items-center gap-2">
        {`hands-on` !== '' && (
                      <span className="text-xs font-semibold uppercase tracking-wider px-2 py-0.5 rounded-md bg-accent-badge border border-accent-soft text-accent">
                        hands-on
                      </span>
                    )}

        <span className="text-xs text-subtle">Thursday, January 5th 2023</span>
      </div>

      <h3 className="blog-card-title group-hover:text-accent transition-colors">Power-up Your Local Development with DDEV</h3>
      <p className="blog-card-desc">Get the best local development experience with the DDEV-Platform.sh add-on. Follow our guide, share your feedback, and optimize your workflow</p>
    </div>
  </a>
</ShowMore>
