diff --git a/package.json b/package.json index 49dc443..427540e 100644 --- a/package.json +++ b/package.json @@ -16,21 +16,22 @@ "dependencies": { "@astrojs/check": "^0.9.4", "@astrojs/tailwind": "^5.1.2", - "astro": "^4.16.14", - "sharp": "^0.33.5", - "typescript": "^5.6.3", + "@astrojs/rss": "^4.0.9", + "@biomejs/biome": "^1.9.4", "@fontsource-variable/onest": "^5.1.0", "@iconify-json/heroicons": "^1.2.1", - "@biomejs/biome": "^1.9.4", + "@resvg/resvg-js": "^2.6.2", "@tailwindcss/typography": "^0.5.15", + "astro": "^4.16.14", "astro-icon": "^1.1.2", + "html-entities": "^2.5.2", "motion": "^11.11.17", + "satori": "^0.12.0", + "satori-html": "^0.3.2", + "sharp": "^0.33.5", + "tailwindcss": "^3.4.15", "tailwind-merge": "^2.5.4", "tailwind-scrollbar": "^3.1.0", - "tailwindcss": "^3.4.15", - "@resvg/resvg-js": "^2.6.2", - "html-entities": "^2.5.2", - "satori": "^0.12.0", - "satori-html": "^0.3.2" + "typescript": "^5.6.3" } } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index da5fb6a..b4fe113 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -11,6 +11,9 @@ importers: '@astrojs/check': specifier: ^0.9.4 version: 0.9.4(typescript@5.6.3) + '@astrojs/rss': + specifier: ^4.0.9 + version: 4.0.9 '@astrojs/tailwind': specifier: ^5.1.2 version: 5.1.2(astro@4.16.14(@types/node@22.9.1)(rollup@4.27.3)(typescript@5.6.3))(tailwindcss@3.4.15) @@ -110,6 +113,9 @@ packages: resolution: {integrity: sha512-Z9IYjuXSArkAUx3N6xj6+Bnvx8OdUSHA8YoOgyepp3+zJmtVYJIl/I18GozdJVW1p5u/CNpl3Km7/gwTJK85cw==} engines: {node: ^18.17.1 || ^20.3.0 || >=21.0.0} + '@astrojs/rss@4.0.9': + resolution: {integrity: sha512-W1qeLc/WP1vMS5xXa+BnaLU0paeSeGjN8RJVAoBaOIkQuKXjIUA9hvPno89heo73in5i67g40gy70oeeHMqp6A==} + '@astrojs/tailwind@5.1.2': resolution: {integrity: sha512-IvOF0W/dtHElcXvhrPR35nHmhyV3cfz1EzPitMGtU7sYy9Hci3BNK1To6FWmVuuNKPxza1IgCGetSynJZL7fOg==} peerDependencies: @@ -1281,6 +1287,10 @@ packages: fast-uri@3.0.3: resolution: {integrity: sha512-aLrHthzCjH5He4Z2H9YZ+v6Ujb9ocRuW6ZzkJQOrTxleEijANq4v1TsaPaVG1PZcuurEzrLcWRyYBYXD5cEiaw==} + fast-xml-parser@4.5.0: + resolution: {integrity: sha512-/PlTQCI96+fZMAOLMZK4CWG1ItCbfZ/0jx7UIJFChPNrx7tcEgerUgWbeieCM9MfHInUDyK8DWYZ+YrywDJuTg==} + hasBin: true + fastq@1.17.1: resolution: {integrity: sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==} @@ -2255,6 +2265,9 @@ packages: resolution: {integrity: sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==} engines: {node: '>=4'} + strnum@1.0.5: + resolution: {integrity: sha512-J8bbNyKKXl5qYcR36TIO8W3mVGVHrmmxsd5PAItGkmyzwJvybiw2IVq5nqd0i4LSNSkB/sx9VHllbfFdr9k1JA==} + sucrase@3.35.0: resolution: {integrity: sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA==} engines: {node: '>=16 || 14 >=14.17'} @@ -2735,6 +2748,11 @@ snapshots: dependencies: prismjs: 1.29.0 + '@astrojs/rss@4.0.9': + dependencies: + fast-xml-parser: 4.5.0 + kleur: 4.1.5 + '@astrojs/tailwind@5.1.2(astro@4.16.14(@types/node@22.9.1)(rollup@4.27.3)(typescript@5.6.3))(tailwindcss@3.4.15)': dependencies: astro: 4.16.14(@types/node@22.9.1)(rollup@4.27.3)(typescript@5.6.3) @@ -3933,6 +3951,10 @@ snapshots: fast-uri@3.0.3: {} + fast-xml-parser@4.5.0: + dependencies: + strnum: 1.0.5 + fastq@1.17.1: dependencies: reusify: 1.0.4 @@ -5150,6 +5172,8 @@ snapshots: strip-bom@3.0.0: {} + strnum@1.0.5: {} + sucrase@3.35.0: dependencies: '@jridgewell/gen-mapping': 0.3.5 diff --git a/public/styles/rss.xsl b/public/styles/rss.xsl new file mode 100644 index 0000000..dfdb0fe --- /dev/null +++ b/public/styles/rss.xsl @@ -0,0 +1,141 @@ + + + + + + + + <xsl:value-of select="/rss/channel/title"/> Web Feed + + + + + + +
+
+

+ + + + + + + + + + + + + + + + + + + Web Feed Preview +

+

+

+ + + + + Visit Website → + +
+

Recent Items

+ +
+

+ + + + + + +

+ + Published: + +
+
+
+ + +
+
\ No newline at end of file diff --git a/src/components/Footer.astro b/src/components/Footer.astro index 76f9c0e..a87695a 100644 --- a/src/components/Footer.astro +++ b/src/components/Footer.astro @@ -1,6 +1,6 @@ --- import { Icon } from 'astro-icon/components'; -import { DISCORD_URL, GITHUB_URL } from '../constants'; +import { DISCORD_URL, GITHUB_URL, SPONSOR_URL } from '../constants'; --- diff --git a/src/components/Head.astro b/src/components/Head.astro index f9b390e..747e74a 100644 --- a/src/components/Head.astro +++ b/src/components/Head.astro @@ -2,14 +2,16 @@ import ThemeManager from './ThemeManager.astro'; import '@fontsource-variable/onest'; import onestWoff2 from '@fontsource-variable/onest/files/onest-latin-wght-normal.woff2?url'; - -const OgBanner = new URL('/og.jpg', Astro.url); interface Props { title?: string; desc?: string; ogImage?: URL | undefined; } +const OgBanner = new URL('/og.jpg', Astro.url); + +const RSSFeed = new URL('rss.xml', Astro.site); + const { title, desc = 'A dedicated CMS for Astro DB.', ogImage = OgBanner } = Astro.props; const studioTitle = `StudioCMS${title ? ` - ${title}` : ''}`; @@ -17,29 +19,41 @@ const studioTitle = `StudioCMS${title ? ` - ${title}` : ''}`; - + {studioTitle} - + + + + + + + + + + diff --git a/src/components/Navbar.astro b/src/components/Navbar.astro index 91c4e4b..3f8cb5b 100644 --- a/src/components/Navbar.astro +++ b/src/components/Navbar.astro @@ -1,6 +1,6 @@ --- import { Icon } from 'astro-icon/components'; -import { DISCORD_URL, DOCS_URL, GITHUB_URL } from '../constants'; +import { DISCORD_URL, DOCS_URL, GITHUB_URL, SPONSOR_URL } from '../constants'; import ThemeSelect from './ThemeSelect.astro'; --- @@ -74,6 +74,20 @@ import ThemeSelect from './ThemeSelect.astro'; /> +
  • + + + +
  • diff --git a/src/constants.ts b/src/constants.ts index 7daf0d3..07ef02c 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -1,7 +1,7 @@ // Keywords for the marquee export const marqueeKeywords = [ '#CMS', - '#Astrolicious', + '#withstudiocms', '#Astro', '#AstroDB', '#libSQL', @@ -12,10 +12,9 @@ export const marqueeKeywords = [ // Links export const GITHUB_URL = 'https://github.com/withstudiocms/studiocms'; -export const SPONSOR_URL = 'https://github.com/withstudiocms'; +export const SPONSOR_URL = 'https://patreon.com/StudioCMS'; export const DISCORD_URL = 'https://chat.studiocms.dev/'; export const DOCS_URL = 'https://docs.studiocms.dev/'; -export const ROADMAP_URL = - 'https://roadmap.studiocms.xyz/spaces/issues/e0f1c24900e44954ba3d93e46d8d8b9d/?board=kanban'; +export const ROADMAP_URL = 'https://github.com/orgs/withstudiocms/projects/1'; // Testimonials and Features have been moved to content collections diff --git a/src/icons/patreon.svg b/src/icons/patreon.svg new file mode 100644 index 0000000..207e13c --- /dev/null +++ b/src/icons/patreon.svg @@ -0,0 +1,8 @@ + + + + + \ No newline at end of file diff --git a/src/pages/blog/index.astro b/src/pages/blog/index.astro index 754c4ec..9334ee7 100644 --- a/src/pages/blog/index.astro +++ b/src/pages/blog/index.astro @@ -1,5 +1,6 @@ --- import { getCollection } from 'astro:content'; +import { Icon } from 'astro-icon/components'; import BlogCard from '../../components/BlogCard.astro'; import BaseLayout from '../../layouts/BaseLayout.astro'; @@ -12,7 +13,7 @@ blogPosts.sort(({ data: { publishDate: a } }, { data: { publishDate: b } }) => {
    -

    The StudioCMS Blog

    +

    The StudioCMS Blog

    Get the latest news from StudioCMS

    { diff --git a/src/pages/index.astro b/src/pages/index.astro index 18d9ca7..753f790 100644 --- a/src/pages/index.astro +++ b/src/pages/index.astro @@ -77,7 +77,7 @@ const features = (await getCollection('features')).sort( href={SPONSOR_URL} >

    Sponsor it

    - +
    diff --git a/src/pages/rss.xml.ts b/src/pages/rss.xml.ts new file mode 100644 index 0000000..f48be1b --- /dev/null +++ b/src/pages/rss.xml.ts @@ -0,0 +1,38 @@ +import { getCollection, getEntry } from 'astro:content'; +import rss from '@astrojs/rss'; +import type { APIContext, APIRoute } from 'astro'; + +import { experimental_AstroContainer as AstroContainer } from 'astro/container'; + +export const GET: APIRoute = async ({ site }: APIContext) => { + // Get the blog collection + const blog = await getCollection('blog'); + + // Create an Astro container to render the blog post content + const container = await AstroContainer.create(); + + return rss({ + title: 'StudioCMS', + description: + 'A dedicated CMS for Astro and Astro DB. Built from the ground up by the Astro community.', + site: site, + trailingSlash: false, + stylesheet: '/styles/rss.xsl', + items: await Promise.all( + blog + .sort( + // Sort the blog posts by publish date from newest to oldest + ({ data: { publishDate: a } }, { data: { publishDate: b } }) => b.getTime() - a.getTime() + ) + .map(async ({ render, slug, data: { title, description, tags, publishDate, author } }) => ({ + title: title, + description: description, + pubDate: publishDate, + categories: tags, + author: (await getEntry(author.collection, author.id)).data.link, + link: `${site}blog/${slug}`, + content: await container.renderToString((await render()).Content), + })) + ), + }); +};