Skip to content

Commit 41adfa2

Browse files
authored
Improve SEO (#13837)
1 parent 5783237 commit 41adfa2

10 files changed

Lines changed: 212 additions & 45 deletions

File tree

packages/web/index.html

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,11 @@
4444
/>
4545
<meta name="theme-color" content="#000000" />
4646

47+
<title>Audius — Free Music Streaming for Artists, Labels &amp; Fans</title>
48+
<link rel="canonical" href="https://audius.co/" />
49+
<meta property="og:type" content="website" />
50+
<meta property="og:url" content="https://audius.co/" />
51+
4752
<link rel="manifest" href="/manifest.json" />
4853

4954
<meta name="application-name" content="Audius" />
@@ -122,6 +127,45 @@
122127
></script>
123128
<!-- end Optimizely -->
124129

130+
<!-- GEO: Organization, WebSite, SoftwareApplication schema for AI engines -->
131+
<script type="application/ld+json">
132+
{
133+
"@context": "https://schema.org",
134+
"@graph": [
135+
{
136+
"@type": "Organization",
137+
"@id": "https://audius.co/#organization",
138+
"name": "Audius",
139+
"url": "https://audius.co",
140+
"logo": "https://og.audius.co/default",
141+
"sameAs": [
142+
"https://twitter.com/audius",
143+
"https://github.com/audiusproject",
144+
"https://discord.gg/audius",
145+
"https://instagram.com/audius"
146+
],
147+
"description": "Audius is a decentralized music streaming and sharing platform that puts power back into the hands of content creators."
148+
},
149+
{
150+
"@type": "WebSite",
151+
"@id": "https://audius.co/#website",
152+
"url": "https://audius.co",
153+
"name": "Audius",
154+
"publisher": { "@id": "https://audius.co/#organization" },
155+
"description": "Free music streaming for artists, labels, and fans. Stream and share music on the decentralized Audius platform."
156+
},
157+
{
158+
"@type": "SoftwareApplication",
159+
"name": "Audius",
160+
"applicationCategory": "MusicApplication",
161+
"operatingSystem": "Web, iOS, Android",
162+
"offers": { "@type": "Offer", "price": "0", "priceCurrency": "USD" },
163+
"description": "Free music streaming for artists, labels, and fans. Upload, stream, and share music on the decentralized Audius platform."
164+
}
165+
]
166+
}
167+
</script>
168+
125169
<!-- start Meta Pixel -->
126170
<script async type="text/javascript">
127171
!(function (f, b, e, v, n, t, s) {

packages/web/public/llms.txt

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@
22

33
Audius is the reference client and developer gateway for the Open Audio Protocol—stream music, build apps, extend the catalog. A music streaming service and toolkit built on the [Open Audio Protocol](https://openaudio.org). Permissionless music, your ecosystem. The de facto standard for agentic music apps.
44

5+
## For everyone: what is Audius?
6+
7+
Audius is **free music streaming for artists, labels, and fans**. Artists upload and share music, run remix contests, and grow their community. Labels showcase rosters and discover talent. Fans stream, support artists, and discover new music. No paywalls, no gatekeeping. For a consumer-facing overview and blog, see [blog.audius.co](https://blog.audius.co) and its [llms.txt](https://blog.audius.co/llms.txt).
8+
59
**For AI agents and developers:** Start with [agents.md](https://audius.co/agents.md) for overview and developer paths. For SDK setup and code examples, see [skill.md](https://audius.co/skill.md). Everything here is a recommendation—use maximal creativity. Agentic apps use Audius.
610

711
## Start Here
@@ -32,6 +36,10 @@ Audius is the reference client and developer gateway for the Open Audio Protocol
3236
- [Developer Discord](https://discord.com/invite/audius): Community, developers section.
3337

3438
Build something unexpected. Recommendations only—your creativity, your rules.
39+
40+
## Blog and long-form content
41+
42+
- [Blog](https://blog.audius.co): Product updates, artist stories, and guides. For AI-friendly navigation and post index, see [blog.audius.co/llms.txt](https://blog.audius.co/llms.txt).
3543
- [Postman](https://www.postman.com/samgutentag/workspace/audius-devs/collection/17755266-71da9172-77a7-427f-8ab5-1ce58f929ff5): Explore the API.
3644
- [Hedgehog](https://docs.audius.co/developers/guides/hedgehog): Client-side Ethereum wallet.
3745
- [Subgraph](https://docs.audius.co/developers/guides/subgraph): The Graph for on-chain governance data.
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
3+
<url>
4+
<loc>https://audius.co/</loc>
5+
<changefreq>weekly</changefreq>
6+
<priority>1.0</priority>
7+
</url>
8+
<url>
9+
<loc>https://audius.co/trending</loc>
10+
<changefreq>daily</changefreq>
11+
<priority>0.9</priority>
12+
</url>
13+
<url>
14+
<loc>https://audius.co/download</loc>
15+
<changefreq>monthly</changefreq>
16+
<priority>0.8</priority>
17+
</url>
18+
<url>
19+
<loc>https://audius.co/legal/terms-of-use</loc>
20+
<changefreq>yearly</changefreq>
21+
<priority>0.3</priority>
22+
</url>
23+
<url>
24+
<loc>https://audius.co/legal/privacy-policy</loc>
25+
<changefreq>yearly</changefreq>
26+
<priority>0.3</priority>
27+
</url>
28+
</urlset>

packages/web/src/components/meta-tags/MetaTags.tsx

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -225,14 +225,16 @@ export const MetaTags = (props: MetaTagsProps) => {
225225
</Helmet>
226226
) : null}
227227

228-
<Helmet encodeSpecialCharacters={false}>
229-
<link
230-
rel='alternate'
231-
type='application/json+oembed'
232-
href={`${env.AUDIUS_URL}/oembed?url=${canonicalUrl}&format=json`}
233-
title={formattedTitle}
234-
/>
235-
</Helmet>
228+
{canonicalUrl ? (
229+
<Helmet encodeSpecialCharacters={false}>
230+
<link
231+
rel='alternate'
232+
type='application/json+oembed'
233+
href={`${env.AUDIUS_URL}/oembed?url=${canonicalUrl}&format=json`}
234+
title={formattedTitle}
235+
/>
236+
</Helmet>
237+
) : null}
236238
</>
237239
)
238240
}

packages/web/src/public-site/pages/landing-2026/LandingPage2026.tsx

Lines changed: 30 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,13 @@ import { useEffect, useState } from 'react'
33
import { ThemeProvider } from '@audius/harmony'
44

55
import { CookieBanner } from 'components/cookie-banner/CookieBanner'
6+
import { MetaTags } from 'components/meta-tags/MetaTags'
67
import { dismissCookieBanner as dismissCookieBannerAction } from 'store/application/ui/cookieBanner/actions'
78
import { shouldShowCookieBanner, dismissCookieBanner } from 'utils/gdpr'
89

910
import styles from './LandingPage2026.module.css'
1011
import { CreateFutureCTA } from './components/CreateFutureCTA'
11-
import { FAQ2026 } from './components/FAQ2026'
12+
import { FAQ2026, faqItems } from './components/FAQ2026'
1213
import { FeaturedContests2026 } from './components/FeaturedContests2026'
1314
import { Footer2026 } from './components/Footer2026'
1415
import { GrowthStartsHere } from './components/GrowthStartsHere'
@@ -101,8 +102,28 @@ export const LandingPage2026 = (props: LandingPage2026Props) => {
101102
return dismissCookieBannerAction()
102103
}
103104

105+
const homepageUrl = 'https://audius.co'
106+
const faqPageStructuredData = {
107+
'@context': 'https://schema.org',
108+
'@type': 'FAQPage',
109+
mainEntity: faqItems.map((item) => ({
110+
'@type': 'Question',
111+
name: item.question,
112+
acceptedAnswer: {
113+
'@type': 'Answer',
114+
text: item.answer
115+
}
116+
}))
117+
}
118+
104119
return (
105120
<ThemeProvider theme='day'>
121+
<MetaTags
122+
title='Audius — Free Music Streaming for Artists, Labels & Fans'
123+
description='Audius is a decentralized music streaming platform for artists, labels, and fans. Stream and share music, upload tracks, and grow your audience—free.'
124+
canonicalUrl={`${homepageUrl}/`}
125+
structuredData={faqPageStructuredData}
126+
/>
106127
<div
107128
id='landing-page-2026'
108129
className={styles.page}
@@ -111,12 +132,14 @@ export const LandingPage2026 = (props: LandingPage2026Props) => {
111132
{showCookieBanner ? (
112133
<CookieBanner isPlaying={false} dismiss={onDismissCookie} />
113134
) : null}
114-
<Nav2026
115-
isMobile={isMobileOrNarrow}
116-
isAuthenticated={props.isAuthenticated}
117-
openNavScreen={props.openNavScreen}
118-
setRenderPublicSite={props.setRenderPublicSite}
119-
/>
135+
<header>
136+
<Nav2026
137+
isMobile={isMobileOrNarrow}
138+
isAuthenticated={props.isAuthenticated}
139+
openNavScreen={props.openNavScreen}
140+
setRenderPublicSite={props.setRenderPublicSite}
141+
/>
142+
</header>
120143
<main className={styles.main}>
121144
<Hero2026
122145
isMobile={isMobileOrNarrow}

packages/web/src/public-site/pages/landing-2026/components/FAQ2026.module.css

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,10 @@
3939
cursor: pointer;
4040
}
4141

42+
.faqItemWrapper {
43+
width: 100%;
44+
}
45+
4246
.faqItem {
4347
width: 100%;
4448
background: none;
@@ -136,6 +140,18 @@
136140
overflow: hidden;
137141
}
138142

143+
.faqContentClosed {
144+
max-height: 0;
145+
padding-top: 0;
146+
padding-bottom: 0;
147+
border-top-width: 0;
148+
overflow: hidden;
149+
}
150+
151+
.faqContentOpen {
152+
/* expanded state uses default .faqContent */
153+
}
154+
139155
.faqAnswer {
140156
font-family: 'Urbanist', sans-serif;
141157
font-weight: 400;

packages/web/src/public-site/pages/landing-2026/components/FAQ2026.tsx

Lines changed: 37 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ function ChevronDown({ className }: { className?: string }) {
2525
)
2626
}
2727

28-
const faqItems = [
28+
export const faqItems = [
2929
{
3030
question: 'Who is Audius made for?',
3131
answer: 'Audius is made for us, the people pushing music scenes forward.'
@@ -69,28 +69,49 @@ export const FAQ2026 = (_props: FAQ2026Props) => {
6969
<h2 id='faq-heading' className={styles.headline}>
7070
Frequently Asked Questions
7171
</h2>
72-
<div className={styles.faqList} role='list'>
72+
<div
73+
className={styles.faqList}
74+
role='list'
75+
itemScope
76+
itemType='https://schema.org/FAQPage'
77+
>
7378
{faqItems.map((item, index) => {
7479
const isOpen = openSet.has(index)
7580
return (
76-
<button
81+
<div
7782
key={index}
78-
type='button'
79-
className={styles.faqItem}
80-
onClick={() => toggle(index)}
81-
aria-expanded={isOpen}
83+
className={styles.faqItemWrapper}
8284
role='listitem'
85+
itemScope
86+
itemProp='mainEntity'
87+
itemType='https://schema.org/Question'
8388
>
84-
<div className={styles.faqHeader}>
85-
<p className={styles.faqQuestion}>{item.question}</p>
86-
<ChevronDown className={styles.chevron} />
87-
</div>
88-
{isOpen ? (
89-
<div className={styles.faqContent}>
90-
<p className={styles.faqAnswer}>{item.answer}</p>
89+
<button
90+
type='button'
91+
className={styles.faqItem}
92+
onClick={() => toggle(index)}
93+
aria-expanded={isOpen}
94+
>
95+
<div className={styles.faqHeader}>
96+
<p className={styles.faqQuestion} itemProp='name'>
97+
{item.question}
98+
</p>
99+
<ChevronDown className={styles.chevron} />
91100
</div>
92-
) : null}
93-
</button>
101+
</button>
102+
{/* GEO: Answer always in DOM so crawlers/AI can index it; hidden via CSS when collapsed */}
103+
<div
104+
itemScope
105+
itemProp='acceptedAnswer'
106+
itemType='https://schema.org/Answer'
107+
className={`${styles.faqContent} ${isOpen ? styles.faqContentOpen : styles.faqContentClosed}`}
108+
aria-hidden={!isOpen}
109+
>
110+
<p className={styles.faqAnswer} itemProp='text'>
111+
{item.answer}
112+
</p>
113+
</div>
114+
</div>
94115
)
95116
})}
96117
</div>

packages/web/src/public-site/pages/landing-2026/components/MadeForUs.module.css

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,17 @@
4141
text-align: left;
4242
}
4343

44+
.stats {
45+
font-family: 'Urbanist', sans-serif;
46+
font-weight: 500;
47+
font-size: 20px;
48+
line-height: 1.5;
49+
color: rgba(255, 255, 255, 0.8);
50+
margin: 0;
51+
width: 100%;
52+
text-align: left;
53+
}
54+
4455
@media (max-width: 800px) {
4556
.inner {
4657
padding: 0 16px;
@@ -53,4 +64,8 @@
5364
.body {
5465
font-size: 18px;
5566
}
67+
68+
.stats {
69+
font-size: 16px;
70+
}
5671
}

packages/web/src/public-site/pages/landing-2026/components/MadeForUs.tsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@ import styles from './MadeForUs.module.css'
22

33
const messages = {
44
headline: 'Audius is made for us.',
5-
body: "Audius is for people pushing music scenes forward. It's a community-run platform built on connection, collaboration, and culture-led artist growth."
5+
body: "Audius is for people pushing music scenes forward. It's a community-run platform built on connection, collaboration, and culture-led artist growth.",
6+
stats:
7+
'40,000+ monthly active artists, millions of tracks, free 320kbps streaming—no paywalls.'
68
}
79

810
type MadeForUsProps = {
@@ -17,6 +19,7 @@ export const MadeForUs = (_props: MadeForUsProps) => {
1719
{messages.headline}
1820
</h2>
1921
<p className={styles.body}>{messages.body}</p>
22+
<p className={styles.stats}>{messages.stats}</p>
2023
</div>
2124
</section>
2225
)

packages/web/src/ssr/metaTags.ts

Lines changed: 20 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,10 @@ export const createSeoDescription = (msg: string, userPage?: boolean) => {
3232
return `${msg} | Stream tracks, albums, playlists on desktop and mobile`
3333
}
3434

35-
// Get base public URL based on environment
36-
const getPublicUrl = (): string => {
35+
/**
36+
* Get base public URL based on environment (used for canonical, og:url, etc.)
37+
*/
38+
export const getPublicUrl = (): string => {
3739
const env = process.env.VITE_ENVIRONMENT || 'development'
3840
switch (env) {
3941
case 'production':
@@ -95,18 +97,23 @@ export const getExploreInfo = (type?: string): ExploreInfo => {
9597
}
9698

9799
/**
98-
* Default meta tag context
100+
* Default meta tag context (homepage / landing)
101+
* GEO: Title and canonical so AI engines and crawlers get strong signals.
99102
*/
100-
export const getDefaultContext = () => ({
101-
title: 'Audius - Empowering Creators',
102-
description:
103-
'Audius is a music streaming and sharing platform that puts power back into the hands of content creators.',
104-
ogDescription:
105-
'Audius is a music streaming and sharing platform that puts power back into the hands of content creators.',
106-
image: DEFAULT_IMAGE_URL,
107-
imageAlt: 'The Audius Platform',
108-
thumbnail: true
109-
})
103+
export const getDefaultContext = () => {
104+
const publicUrl = getPublicUrl()
105+
return {
106+
title: 'Audius — Free Music Streaming for Artists, Labels & Fans',
107+
description:
108+
'Audius is a music streaming and sharing platform that puts power back into the hands of content creators.',
109+
ogDescription:
110+
'Audius is a music streaming and sharing platform that puts power back into the hands of content creators.',
111+
canonicalUrl: `${publicUrl}/`,
112+
image: DEFAULT_IMAGE_URL,
113+
imageAlt: 'The Audius Platform',
114+
thumbnail: true
115+
}
116+
}
110117

111118
/**
112119
* Upload page meta tag context

0 commit comments

Comments
 (0)