diff --git a/.changeset/curvy-stingrays-decide.md b/.changeset/curvy-stingrays-decide.md
new file mode 100644
index 00000000..16503a83
--- /dev/null
+++ b/.changeset/curvy-stingrays-decide.md
@@ -0,0 +1,5 @@
+---
+"eslint-plugin-primer-react": patch
+---
+
+Add rule for Link to not be allowed without href
diff --git a/src/rules/__tests__/enforce-button-for-link-with-nohref.test.js b/src/rules/__tests__/enforce-button-for-link-with-nohref.test.js
new file mode 100644
index 00000000..847d192c
--- /dev/null
+++ b/src/rules/__tests__/enforce-button-for-link-with-nohref.test.js
@@ -0,0 +1,86 @@
+const rule = require('../enforce-button-for-link-with-nohref')
+const {RuleTester} = require('eslint')
+
+const ruleTester = new RuleTester({
+ parserOptions: {
+ ecmaVersion: 'latest',
+ sourceType: 'module',
+ ecmaFeatures: {
+ jsx: true,
+ },
+ },
+})
+
+ruleTester.run('enforce-button-for-link-with-nohref', rule, {
+ valid: [
+ // Link with href attribute
+ `import {Link} from '@primer/react';
+ Valid Link`,
+
+ // Link with href and inline prop
+ `import {Link} from '@primer/react';
+ Valid Inline Link`,
+
+ // Link with href and className
+ `import {Link} from '@primer/react';
+ Valid Link with Class`,
+
+ // Link with href, inline, and className
+ `import {Link} from '@primer/react';
+ Valid Inline Link with Class`,
+
+ // Link with href as variable
+ `import {Link} from '@primer/react';
+ const url = '/about';
+ About`,
+
+ // Button component (not Link)
+ `import {Button} from '@primer/react';
+ `,
+
+ // Regular HTML link (not Primer Link)
+ `Click me`,
+
+ // Link from different package
+ `import {Link} from 'react-router-dom';
+ About`,
+ ],
+ invalid: [
+ {
+ code: `import {Link} from '@primer/react';
+ Invalid Link without href`,
+ errors: [
+ {
+ messageId: 'noLinkWithoutHref',
+ },
+ ],
+ },
+ {
+ code: `import {Link} from '@primer/react';
+ Invalid Link with class but no href`,
+ errors: [
+ {
+ messageId: 'noLinkWithoutHref',
+ },
+ ],
+ },
+ {
+ code: `import {Link} from '@primer/react';
+ Invalid inline Link without href`,
+ errors: [
+ {
+ messageId: 'noLinkWithoutHref',
+ },
+ ],
+ },
+ {
+ code: `import {Link} from '@primer/react';
+ Invalid Link with onClick but no href`,
+ errors: [
+ {
+ messageId: 'noLinkWithoutHref',
+ },
+ ],
+ },
+ ],
+})
diff --git a/src/rules/enforce-button-for-link-with-nohref.js b/src/rules/enforce-button-for-link-with-nohref.js
new file mode 100644
index 00000000..957169de
--- /dev/null
+++ b/src/rules/enforce-button-for-link-with-nohref.js
@@ -0,0 +1,41 @@
+const url = require('../url')
+const {getJSXOpeningElementAttribute} = require('../utils/get-jsx-opening-element-attribute')
+const {getJSXOpeningElementName} = require('../utils/get-jsx-opening-element-name')
+const {isPrimerComponent} = require('../utils/is-primer-component')
+
+module.exports = {
+ meta: {
+ type: 'error',
+ docs: {
+ description: 'Disallow usage of Link component without href',
+ recommended: true,
+ url: url(module),
+ },
+ messages: {
+ noLinkWithoutHref: 'Links without href and other side effects are not accessible. Use a Button instead.',
+ },
+ },
+
+ create(context) {
+ const sourceCode = context.sourceCode ?? context.getSourceCode()
+ return {
+ JSXElement(node) {
+ const openingElement = node.openingElement
+ const elementName = getJSXOpeningElementName(openingElement)
+
+ // Check if this is a Link component from @primer/react
+ if (elementName === 'Link' && isPrimerComponent(openingElement.name, sourceCode.getScope(node))) {
+ // Check if the Link has an href attribute
+ const hrefAttribute = getJSXOpeningElementAttribute(openingElement, 'href')
+
+ if (!hrefAttribute) {
+ context.report({
+ node: openingElement,
+ messageId: 'noLinkWithoutHref',
+ })
+ }
+ }
+ },
+ }
+ },
+}