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

# Bazel Rules by Aspect

> We wrote and maintain rules_py, rules_js, rules_ts, rules_lint, rules_oci, bazel-lib, and the surrounding rulesets that thousands of engineering teams build on. Free and Apache 2.0 licensed.

export const MarketingPage = () => <div className="marketing-page-marker" style={{
  display: "none"
}} />;

export const CTA = ({title, subtitle, primaryCta, primaryHref = "#", secondaryCta, secondaryHref = "#"}) => <section className="w-full flex justify-center px-4 py-16 md:py-20">
    <div className="w-full rounded-2xl text-white flex flex-col md:flex-row items-center justify-center gap-10 md:gap-16 p-8 md:p-12 text-center md:text-left" style={{
  maxWidth: "1140px",
  background: "linear-gradient(135deg, #1a3a5c 0%, #176ACC 100%)"
}}>
      <div>
        <h2 className="text-2xl md:text-3xl font-semibold tracking-tight">{title}</h2>
        {subtitle && <div className="mt-3 text-blue-100 text-base">{subtitle}</div>}
      </div>
      <div className="flex flex-wrap gap-3 shrink-0 justify-center">
        {primaryCta && <a href={primaryHref} className="inline-flex items-center px-6 py-3 rounded-lg bg-white text-blue-700 font-semibold hover:bg-blue-50 transition whitespace-nowrap shadow-sm">
            {primaryCta}
          </a>}
        {secondaryCta && <a href={secondaryHref} className={`inline-flex items-center px-6 py-3 rounded-lg border border-blue-300/50 text-white font-semibold hover:bg-blue-700/30 transition whitespace-nowrap ${secondaryHref === "/request-demo" ? "demo-gradient-btn" : ""}`}>
            {secondaryCta}
          </a>}
      </div>
    </div>
  </section>;

export const MediaCard = ({title, description, href, linkText = "Learn more", external = false, children}) => {
  const Tag = href ? "a" : "div";
  const tagProps = href ? {
    href,
    ...external ? {
      target: "_blank",
      rel: "noopener noreferrer"
    } : {}
  } : {};
  return <Tag {...tagProps} className="group flex flex-col rounded-xl border border-zinc-200 dark:border-zinc-700/60 bg-white dark:bg-zinc-800/50 overflow-hidden hover:shadow-md hover:border-blue-200 dark:hover:border-blue-700 transition-all duration-200">
      {children && <div className="media-card-image aspect-[16/10] overflow-hidden bg-zinc-50 dark:bg-zinc-900">
          {children}
        </div>}
      <div className="flex flex-col flex-1 p-6">
        <h3 className="text-lg font-semibold text-zinc-900 dark:text-white group-hover:text-blue-600 dark:group-hover:text-blue-400 transition-colors">
          {title}
        </h3>
        {description && <p className="feature-card-desc text-sm text-zinc-500 dark:text-zinc-400 leading-relaxed flex-1">{description}</p>}
        {linkText && href && <span className="inline-flex items-center mt-4 text-sm text-blue-600 dark:text-blue-400 font-semibold group-hover:underline underline-offset-2">
            {linkText} {external ? "↗" : "→"}
          </span>}
      </div>
    </Tag>;
};

export const FeatureCard = ({title, description, href, children}) => {
  const Tag = href ? "a" : "div";
  const tagProps = href ? {
    href
  } : {};
  return <Tag {...tagProps} className={`group flex flex-col p-6 rounded-xl border border-zinc-200 dark:border-zinc-700/60 bg-white dark:bg-zinc-800/50 ${href ? "hover:shadow-md hover:border-blue-200 dark:hover:border-blue-700 transition-all duration-200" : ""}`}>
      {children && <div className="feature-card-icon mb-5 flex items-center justify-center rounded-xl bg-blue-50 dark:bg-blue-900/20 border border-blue-100 dark:border-blue-800/30" style={{
    width: "4rem",
    height: "4rem"
  }}>
          {children}
        </div>}
      <h3 className={`text-lg font-semibold text-zinc-900 dark:text-white ${href ? "group-hover:text-blue-600 dark:group-hover:text-blue-400 transition-colors" : ""}`}>
        {title}
      </h3>
      {description && <p className="feature-card-desc text-sm text-zinc-500 dark:text-zinc-400 leading-relaxed">{description}</p>}
    </Tag>;
};

export const FeatureGrid3 = ({children}) => <div className="marketing-grid-3">{children}</div>;

export const SectionHeader = ({title, subtitle, centered = true, label}) => <div className={`mb-12 ${centered ? "text-center" : ""}`}>
    {label && <p className="text-xs font-semibold tracking-widest text-blue-600 dark:text-blue-400 uppercase mb-3">
        {label}
      </p>}
    <h2 className="text-3xl md:text-5xl font-semibold text-zinc-900 dark:text-white tracking-tight">{title}</h2>
    {subtitle && <div className={`subtitle-gap text-lg md:text-xl text-zinc-500 dark:text-zinc-300 leading-relaxed ${centered ? "mx-auto" : ""}`} style={{
  marginTop: "1rem",
  maxWidth: centered ? "700px" : "none"
}}>
        {subtitle}
      </div>}
  </div>;

export const Section = ({children, className = "", gray = false, dark = false, id}) => <section id={id} className={`w-full flex justify-center px-4 py-16 md:py-24 ${gray ? "bg-gray-50 dark:bg-zinc-900" : dark ? "bg-zinc-900 dark:bg-zinc-950" : ""} ${className}`}>
    <div className="w-full" style={{
  maxWidth: "1140px"
}}>
      {children}
    </div>
  </section>;

export const Hero = ({title, subtitle, badge, eyebrow, heroImageClassName = "", primaryCta, primaryHref = "#", secondaryCta, secondaryHref = "#", note, centered = true, children}) => <section className="w-full flex justify-center px-4 pt-16 pb-16 md:pt-24 md:pb-24" style={{
  background: "linear-gradient(180deg, var(--hero-gradient-start, #f8fafc) 0%, var(--hero-gradient-end, #ffffff) 100%)"
}}>
    <div className="w-full" style={{
  maxWidth: "1140px"
}}>
      {centered && !children ? <div className="flex flex-col items-center text-center">
          {badge && <div className="inline-flex items-center gap-2 px-4 py-1.5 rounded-full bg-blue-50 dark:bg-blue-900/30 border border-blue-200 dark:border-blue-700 text-blue-700 dark:text-blue-300 text-sm font-medium mb-6">
              {badge}
            </div>}
          {eyebrow && <div className="text-xs font-semibold tracking-widest uppercase text-blue-600 dark:text-blue-400 mb-4">
              {eyebrow}
            </div>}
          <h1 className="text-4xl md:text-5xl font-semibold text-zinc-900 dark:text-white leading-tight tracking-tight" style={{
  maxWidth: "820px"
}}>
            {String(title).split(/\\n|\n/).map((line, i) => i ? [<br key={i} />, line] : line)}
          </h1>
          {subtitle && <div className="subtitle-gap text-lg md:text-xl text-zinc-500 dark:text-zinc-300 leading-relaxed" style={{
  marginTop: "1rem",
  maxWidth: "600px"
}}>
              {subtitle}
            </div>}
          {(primaryCta || secondaryCta) && <div className="flex flex-wrap gap-3 mt-10 justify-center">
            {primaryCta && <a href={primaryHref} className="inline-flex items-center px-6 py-3 rounded-lg bg-blue-600 text-white font-semibold hover:bg-blue-700 transition shadow-sm">
                {primaryCta}
              </a>}
            {secondaryCta && <a href={secondaryHref} className={`inline-flex items-center px-6 py-3 rounded-lg border border-zinc-300 dark:border-zinc-600 text-zinc-700 dark:text-zinc-200 font-semibold hover:bg-zinc-50 dark:hover:bg-zinc-800 transition ${secondaryHref === "/request-demo" ? "demo-gradient-btn" : ""}`}>
                {secondaryCta}
              </a>}
          </div>}
          {note && <div className="mt-4 text-sm text-center text-zinc-500 dark:text-zinc-400">{note}</div>}
        </div> : <div className="flex flex-col md:flex-row items-center gap-10 md:gap-16">
          <div className="flex-1 min-w-0">
            {badge && <div className="inline-flex items-center gap-2 px-4 py-1.5 rounded-full bg-blue-50 dark:bg-blue-900/30 border border-blue-200 dark:border-blue-700 text-blue-700 dark:text-blue-300 text-sm font-medium mb-6">
                {badge}
              </div>}
            {eyebrow && <div className="text-xs font-semibold tracking-widest uppercase text-blue-600 dark:text-blue-400 mb-4">
                {eyebrow}
              </div>}
            <h1 className="text-4xl md:text-5xl font-semibold text-zinc-900 dark:text-white leading-tight tracking-tight">
            {String(title).split(/\\n|\n/).map((line, i) => i ? [<br key={i} />, line] : line)}
          </h1>
            {subtitle && <div className="subtitle-gap text-lg md:text-xl text-zinc-500 dark:text-zinc-300 leading-relaxed" style={{
  marginTop: "1rem"
}}>
                {subtitle}
              </div>}
            <div className="flex flex-wrap gap-3 mt-8">
              {primaryCta && <a href={primaryHref} className="inline-flex items-center px-6 py-3 rounded-lg bg-blue-600 text-white font-semibold hover:bg-blue-700 transition shadow-sm">
                  {primaryCta}
                </a>}
              {secondaryCta && <a href={secondaryHref} className={`inline-flex items-center px-6 py-3 rounded-lg border border-zinc-300 dark:border-zinc-600 text-zinc-700 dark:text-zinc-200 font-semibold hover:bg-zinc-50 dark:hover:bg-zinc-800 transition ${secondaryHref === "/request-demo" ? "demo-gradient-btn" : ""}`}>
                  {secondaryCta}
                </a>}
            </div>
            {note && <div className="mt-4 text-sm text-zinc-500 dark:text-zinc-400">{note}</div>}
          </div>
          {children && <div className={`flex-1 min-w-0 hero-image ${heroImageClassName}`}>
              {children}
            </div>}
        </div>}
    </div>
  </section>;

<MarketingPage />

<Hero eyebrow="Open source" title={"The Bazel rules thousands\nof teams build on"} subtitle="rules_py, rules_js, rules_ts, rules_lint and 20+ more, Apache 2.0, with support when you need it." primaryCta="Read the docs" primaryHref="/docs/bazel" secondaryCta="View on GitHub" secondaryHref="https://github.com/aspect-build" centered={false}>
  <div className="marketing-grid-2" style={{ gap: "0.75rem" }}>
    <a href="https://github.com/aspect-build/rules_py" className="p-4 rounded-xl border border-zinc-200 dark:border-zinc-700 bg-white dark:bg-zinc-800 hover:border-blue-300 transition">
      <div className="font-mono text-sm font-semibold text-zinc-900 dark:text-white">rules\_py</div>
      <div className="mt-1 text-xs text-zinc-500 dark:text-zinc-400">Python</div>
    </a>

    <a href="https://github.com/aspect-build/rules_js" className="p-4 rounded-xl border border-zinc-200 dark:border-zinc-700 bg-white dark:bg-zinc-800 hover:border-blue-300 transition">
      <div className="font-mono text-sm font-semibold text-zinc-900 dark:text-white">rules\_js</div>
      <div className="mt-1 text-xs text-zinc-500 dark:text-zinc-400">JavaScript</div>
    </a>

    <a href="https://github.com/aspect-build/rules_ts" className="p-4 rounded-xl border border-zinc-200 dark:border-zinc-700 bg-white dark:bg-zinc-800 hover:border-blue-300 transition">
      <div className="font-mono text-sm font-semibold text-zinc-900 dark:text-white">rules\_ts</div>
      <div className="mt-1 text-xs text-zinc-500 dark:text-zinc-400">TypeScript</div>
    </a>

    <a href="https://github.com/aspect-build/rules_lint" className="p-4 rounded-xl border border-zinc-200 dark:border-zinc-700 bg-white dark:bg-zinc-800 hover:border-blue-300 transition">
      <div className="font-mono text-sm font-semibold text-zinc-900 dark:text-white">rules\_lint</div>
      <div className="mt-1 text-xs text-zinc-500 dark:text-zinc-400">Linting and formatting</div>
    </a>

    <a href="https://github.com/bazel-contrib/rules_oci" className="p-4 rounded-xl border border-zinc-200 dark:border-zinc-700 bg-white dark:bg-zinc-800 hover:border-blue-300 transition">
      <div className="font-mono text-sm font-semibold text-zinc-900 dark:text-white">rules\_oci</div>
      <div className="mt-1 text-xs text-zinc-500 dark:text-zinc-400">Container images</div>
    </a>

    <a href="https://github.com/bazel-contrib/bazel-lib" className="p-4 rounded-xl border border-zinc-200 dark:border-zinc-700 bg-white dark:bg-zinc-800 hover:border-blue-300 transition">
      <div className="font-mono text-sm font-semibold text-zinc-900 dark:text-white">bazel-lib</div>
      <div className="mt-1 text-xs text-zinc-500 dark:text-zinc-400">Shared building blocks</div>
    </a>
  </div>
</Hero>

<Section>
  <div className="marketing-grid-2 max-w-5xl mx-auto" style={{ gap: "2.5rem 4rem" }}>
    <div>
      <div className="text-xs font-semibold tracking-widest uppercase text-zinc-500 mb-3">Why it matters</div>
      <div className="text-lg text-zinc-700 dark:text-zinc-300 leading-relaxed">Bazel is only as good as its rules. For two of the most widely used ecosystems, the rulesets the community builds on were written by Aspect, and we maintain them today.</div>
    </div>

    <div>
      <div className="text-xs font-semibold tracking-widest uppercase text-blue-600 dark:text-blue-400 mb-3">With Aspect</div>
      <div className="text-lg text-zinc-700 dark:text-zinc-300 leading-relaxed">When you build on our rules, the same engineers who wrote them answer your questions, fix the bugs, and ship the releases.</div>
    </div>
  </div>

  <div className="mt-10 text-center">
    <a href="/open-source/stats" className="text-blue-600 dark:text-blue-400 font-semibold hover:underline">
      See which Bazel and module versions our rulesets' users run, on the public ecosystem stats page →
    </a>
  </div>
</Section>

<Section gray>
  <SectionHeader title="The ecosystems we build and maintain" subtitle="Deep, documented support, from first build to advanced patterns, written by the authors of the rules." />

  <FeatureGrid3>
    <FeatureCard title="Python" description="rules_py with native uv integration, hermetic interpreters, and optimized OCI image layers. Drop-in replacements for py_binary, py_library, and py_test." href="/docs/bazel/python" linkText="Python docs">
      <img noZoom src="https://mintcdn.com/aspectbuild/x1L7Iep716jCyJVo/images/marketing/icons/puzzle.svg?fit=max&auto=format&n=x1L7Iep716jCyJVo&q=85&s=d7988f951af9de3713bb62f795bc3da2" alt="" width="40" height="40" data-path="images/marketing/icons/puzzle.svg" />
    </FeatureCard>

    <FeatureCard title="JavaScript & TypeScript" description="rules_js and rules_ts with pnpm workspaces. Integrations for esbuild, webpack, Jest, Cypress, Vite, and Next.js." href="/docs/bazel/javascript" linkText="JS & TS docs">
      <img noZoom src="https://mintcdn.com/aspectbuild/x1L7Iep716jCyJVo/images/marketing/icons/Extension.svg?fit=max&auto=format&n=x1L7Iep716jCyJVo&q=85&s=3239bb28f38ff4a7e9d06bace830bac7" alt="" width="32" height="32" data-path="images/marketing/icons/Extension.svg" />
    </FeatureCard>

    <FeatureCard title="Linting and formatting" description="rules_lint runs linters and formatters as standard Bazel actions across 20+ tools, incremental, cache-aware, and hold-the-line." href="/docs/bazel/linting" linkText="Linting docs">
      <img noZoom src="https://mintcdn.com/aspectbuild/x1L7Iep716jCyJVo/images/marketing/icons/Linting.svg?fit=max&auto=format&n=x1L7Iep716jCyJVo&q=85&s=3bfc20666b4b77e26bb1027a52d6075c" alt="" width="48" height="48" data-path="images/marketing/icons/Linting.svg" />
    </FeatureCard>
  </FeatureGrid3>
</Section>

<Section>
  <SectionHeader title="Why teams build on Aspect rules" />

  <FeatureGrid3>
    <FeatureCard title="Maintained by the authors" description="Releases, bug fixes, and reviews come from the engineers who wrote the rules and use them in production with customers every day." />

    <FeatureCard title="Free and open source" description="Apache 2.0 licensed, no account required. Used by thousands of engineering teams worldwide." />

    <FeatureCard title="BUILD generation included" description="aspect gazelle generates and syncs BUILD files for our rulesets out of the box, so adopting them doesn't mean writing BUILD files by hand." />
  </FeatureGrid3>

  <p className="mt-10 text-center text-sm text-zinc-500 dark:text-zinc-400">
    Beyond these ecosystems, we maintain <a href="https://github.com/bazel-contrib/rules_oci" className="text-blue-600 dark:text-blue-400 font-semibold hover:underline">rules\_oci</a> for building OCI container images without Docker, <a href="https://github.com/bazel-contrib/bazel-lib" className="text-blue-600 dark:text-blue-400 font-semibold hover:underline">bazel-lib</a>, the common utility rules most rulesets build on, plus Gazelle generators, examples, and more. See the full <a href="/docs/bazel/open-source" className="text-blue-600 dark:text-blue-400 font-semibold hover:underline">Open Source Projects</a> listing. Read why we build in the open on <a href="/open-source" className="text-blue-600 dark:text-blue-400 font-semibold hover:underline">our open source page</a>.
  </p>

  <div className="mt-8 text-center">
    <a href="https://signup.aspect.build/" className="text-blue-600 dark:text-blue-400 font-semibold hover:underline">
      Cache the builds these rules produce, free on Aspect Cloud →
    </a>
  </div>
</Section>

<CTA title="Build on rules the authors stand behind" subtitle="Free to use today. Commercial support is there when you want the authors on call." primaryCta="Read the docs" primaryHref="/docs/bazel" secondaryCta="Get support" secondaryHref="/services" />


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.