create-rush-cms 0.1.0 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-rush-cms",
3
- "version": "0.1.0",
3
+ "version": "0.2.1",
4
4
  "description": "Create an Astro website powered by Rush CMS.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -52,19 +52,20 @@ no navigation links. See [Routes](https://github.com/rush-cms/js/tree/main/packa
52
52
 
53
53
  No page file encodes a URL shape:
54
54
 
55
- | File | Answers |
56
- | ------------------------------------- | ----------------------------------------------------------------------------- |
57
- | `src/pages/[...path].astro` | Every homepage, collection list page and entry, prerendered at build time |
58
- | `src/pages/404.astro` | Every other path, on demand: redirects retired slugs, else the not-found page |
59
- | `src/pages/[...locale]/contact.astro` | The contact form of each locale, on demand |
60
- | `src/pages/sitemap.xml.ts` | The sitemap, from the same routes |
61
- | `src/pages/robots.txt.ts` | `robots.txt` (everything disallowed in a preview deployment) |
55
+ | File | Answers |
56
+ | ------------------------------------- | -------------------------------------------------------------------------------- |
57
+ | `src/pages/[...path].astro` | Every homepage, list page, taxonomy listing and entry, prerendered at build time |
58
+ | `src/pages/404.astro` | Every other path, on demand: redirects retired slugs, else the not-found page |
59
+ | `src/pages/[...locale]/contact.astro` | The contact form of each locale, on demand |
60
+ | `src/pages/sitemap.xml.ts` | The sitemap, from the same routes |
61
+ | `src/pages/robots.txt.ts` | `robots.txt` (everything disallowed in a preview deployment) |
62
62
 
63
63
  The dispatcher hands each page to a view:
64
64
 
65
65
  - `src/views/home.astro`: the front page of every locale. It is a static welcome page; replace it with your design,
66
66
  or render the homepage built in Rush CMS from `page.homepage`.
67
67
  - `src/views/collection.astro`: a collection list page with pagination.
68
+ - `src/views/taxonomy.astro`: the entries of a category or tag, with pagination (see [Taxonomies](#taxonomies)).
68
69
  - `src/views/entry.astro`: an entry with its title, featured image, excerpt and every rich-text field.
69
70
  - `src/views/not-found.astro`: the 404 page.
70
71
 
@@ -79,6 +80,26 @@ const views: ViewMap = { posts: { entry: PostEntry } }
79
80
  A view receives the same props as the generic one (`EntryViewProps` or `ListViewProps`), and `npm run check` fails
80
81
  when it does not. `src/astro-modules.d.ts` lets plain TypeScript read the `.astro` imports of that file.
81
82
 
83
+ ## Taxonomies
84
+
85
+ Categories and tags have no pages until `taxonomies` in `astro.config.ts` gives their type a path segment in every
86
+ locale of `localePaths`:
87
+
88
+ ```ts
89
+ taxonomies: {
90
+ category: { en: 'category', pt_BR: 'categoria' },
91
+ tag: { en: 'tag', pt_BR: 'tag' }
92
+ }
93
+ ```
94
+
95
+ Each category or tag with entries then gets a listing page per locale (`/category/design`, `/pt/categoria/design`,
96
+ `/category/design/page/2`), rendered by `src/views/taxonomy.astro` (`TaxonomyViewProps`) and listed in the sitemap.
97
+ The language switcher and the `hreflang` links of a listing point at the same category or tag in the other locales
98
+ (`page.alternates`). A locale where it has no entries gets no `hreflang` link, and its switcher link goes to its
99
+ homepage.
100
+ Link to one with `getUrls(Astro).taxonomy(tag, locale)`, for instance from an entry's `categories`. See
101
+ [Taxonomies](https://github.com/rush-cms/js/tree/main/packages/astro#taxonomies) for the rules.
102
+
82
103
  ## Navigation and forms
83
104
 
84
105
  Site content is fetched by stable keys that you create in Rush CMS:
@@ -14,8 +14,8 @@
14
14
  },
15
15
  "dependencies": {
16
16
  "@astrojs/node": "11.1.11",
17
- "@rushcms/astro": "0.2.0",
18
- "@rushcms/client": "4.0.0",
17
+ "@rushcms/astro": "0.3.1",
18
+ "@rushcms/client": "4.1.0",
19
19
  "@tailwindcss/typography": "0.5.20",
20
20
  "@tailwindcss/vite": "4.3.5",
21
21
  "astro": "7.4.7",
@@ -0,0 +1,95 @@
1
+ ---
2
+ import { getRush, getUrls } from '@rushcms/astro'
3
+ import Hreflang from '@rushcms/astro/components/hreflang.astro'
4
+ import RushImage from '@rushcms/astro/components/rush-image.astro'
5
+ import type { Alternate, Entry, LocaleCode } from '@rushcms/client'
6
+ import Base from '../layouts/base.astro'
7
+ import { formatDate } from '../lib/locale'
8
+
9
+ type PageUrl = (page: number) => string | undefined
10
+
11
+ type Props = {
12
+ locale: LocaleCode
13
+ title: string
14
+ page: number
15
+ lastPage: number
16
+ entries: Entry[]
17
+ pageUrl: PageUrl
18
+ translations?: Alternate[]
19
+ }
20
+
21
+ const { locale, title, page, lastPage, entries, pageUrl, translations = [] } = Astro.props
22
+ const urls = getUrls(Astro)
23
+ const site = await getRush(Astro).site.get()
24
+ const previous = page > 1 ? pageUrl(page - 1) : undefined
25
+ const next = page < lastPage ? pageUrl(page + 1) : undefined
26
+ const current = pageUrl(page)
27
+ const canonical = Astro.site && current !== undefined ? new URL(current, Astro.site) : undefined
28
+ const heading = page > 1 ? `${title} (${page}/${lastPage})` : title
29
+ ---
30
+
31
+ <Base locale={locale} title={`${heading} | ${site.name}`} translations={translations}>
32
+ {canonical && <link slot="head" rel="canonical" href={canonical.href} />}
33
+ {page === 1 && <Hreflang slot="head" alternates={translations} />}
34
+ <div class="mx-auto max-w-6xl px-6 py-16">
35
+ <header class="max-w-3xl">
36
+ <h1 class="text-4xl font-semibold tracking-tight">{title}</h1>
37
+ {
38
+ lastPage > 1 && (
39
+ <p class="mt-2 text-muted">
40
+ Page {page} of {lastPage}
41
+ </p>
42
+ )
43
+ }
44
+ </header>
45
+ {
46
+ entries.length > 0 ? (
47
+ <ul class="mt-12 grid gap-6 sm:grid-cols-2 lg:grid-cols-3">
48
+ {entries.map((entry) => (
49
+ <li>
50
+ <article class="card group relative flex h-full flex-col">
51
+ {entry.featured_image?.url && (
52
+ <RushImage
53
+ media={entry.featured_image}
54
+ class="mb-4 aspect-video w-full rounded-lg object-cover"
55
+ />
56
+ )}
57
+ <h2 class="text-lg font-medium group-hover:text-accent">
58
+ <a href={urls.servedPath(entry, locale)} class="after:absolute after:inset-0">
59
+ {entry.title}
60
+ </a>
61
+ </h2>
62
+ {entry.excerpt && <p class="mt-2 line-clamp-3 text-muted">{entry.excerpt}</p>}
63
+ <p class="mt-auto pt-4 text-sm text-muted">
64
+ <time datetime={entry.published_at}>
65
+ {formatDate(entry.published_at, locale)}
66
+ </time>
67
+ </p>
68
+ </article>
69
+ </li>
70
+ ))}
71
+ </ul>
72
+ ) : (
73
+ <p class="mt-12 text-muted">Nothing has been published here yet.</p>
74
+ )
75
+ }
76
+ {
77
+ lastPage > 1 && (
78
+ <nav aria-label="Pagination" class="mt-12 flex items-center justify-between gap-4">
79
+ {previous ? (
80
+ <a href={previous} rel="prev" class="button button-secondary">
81
+ Previous page
82
+ </a>
83
+ ) : (
84
+ <span />
85
+ )}
86
+ {next && (
87
+ <a href={next} rel="next" class="button button-secondary">
88
+ Next page
89
+ </a>
90
+ )}
91
+ </nav>
92
+ )
93
+ }
94
+ </div>
95
+ </Base>
@@ -5,6 +5,7 @@ import { routePage } from '../lib/route-page'
5
5
  import Home from '../views/home.astro'
6
6
  import { viewsFor } from '../views/index'
7
7
  import NotFound from '../views/not-found.astro'
8
+ import Taxonomy from '../views/taxonomy.astro'
8
9
 
9
10
  export * from '@rushcms/astro/site-paths'
10
11
 
@@ -28,5 +29,6 @@ const { list: List, entry: Entry } = viewsFor(collection, getUrls(Astro))
28
29
 
29
30
  {page.kind === 'homepage' && <Home page={page} />}
30
31
  {page.kind === 'collection' && <List page={page} />}
32
+ {page.kind === 'taxonomy' && <Taxonomy page={page} />}
31
33
  {page.kind === 'found' && <Entry entry={page.entry} locale={page.locale} />}
32
34
  {page.kind === 'missing' && <NotFound />}
@@ -1,84 +1,21 @@
1
1
  ---
2
- import { collectionAlternates, getRush, getUrls } from '@rushcms/astro'
3
- import RushImage from '@rushcms/astro/components/rush-image.astro'
4
- import Base from '../layouts/base.astro'
5
- import { formatDate } from '../lib/locale'
2
+ import { collectionAlternates, getUrls } from '@rushcms/astro'
3
+ import ListPage from '../components/list-page.astro'
6
4
  import type { ListViewProps } from './index'
7
5
 
8
6
  type Props = ListViewProps
9
7
 
10
8
  const { page } = Astro.props
11
- const { collection, locale, entries, lastPage } = page
9
+ const { collection, locale } = page
12
10
  const urls = getUrls(Astro)
13
- const site = await getRush(Astro).site.get()
14
- const previous = page.page > 1 ? urls.collection(collection, locale, page.page - 1) : undefined
15
- const next = page.page < lastPage ? urls.collection(collection, locale, page.page + 1) : undefined
16
- const canonical = Astro.site && new URL(urls.collection(collection, locale, page.page), Astro.site)
17
- const heading = page.page > 1 ? `${collection.name} (${page.page}/${lastPage})` : collection.name
18
- const translations = collectionAlternates(collection.id, urls)
19
11
  ---
20
12
 
21
- <Base locale={locale} title={`${heading} | ${site.name}`} translations={translations}>
22
- {canonical && <link slot="head" rel="canonical" href={canonical.href} />}
23
- <div class="mx-auto max-w-6xl px-6 py-16">
24
- <header class="max-w-3xl">
25
- <h1 class="text-4xl font-semibold tracking-tight">{collection.name}</h1>
26
- {
27
- lastPage > 1 && (
28
- <p class="mt-2 text-muted">
29
- Page {page.page} of {lastPage}
30
- </p>
31
- )
32
- }
33
- </header>
34
- {
35
- entries.items.length > 0 ? (
36
- <ul class="mt-12 grid gap-6 sm:grid-cols-2 lg:grid-cols-3">
37
- {entries.items.map((entry) => (
38
- <li>
39
- <article class="card group relative flex h-full flex-col">
40
- {entry.featured_image?.url && (
41
- <RushImage
42
- media={entry.featured_image}
43
- class="mb-4 aspect-video w-full rounded-lg object-cover"
44
- />
45
- )}
46
- <h2 class="text-lg font-medium group-hover:text-accent">
47
- <a href={urls.servedPath(entry, locale)} class="after:absolute after:inset-0">
48
- {entry.title}
49
- </a>
50
- </h2>
51
- {entry.excerpt && <p class="mt-2 line-clamp-3 text-muted">{entry.excerpt}</p>}
52
- <p class="mt-auto pt-4 text-sm text-muted">
53
- <time datetime={entry.published_at}>
54
- {formatDate(entry.published_at, locale)}
55
- </time>
56
- </p>
57
- </article>
58
- </li>
59
- ))}
60
- </ul>
61
- ) : (
62
- <p class="mt-12 text-muted">Nothing has been published here yet.</p>
63
- )
64
- }
65
- {
66
- lastPage > 1 && (
67
- <nav aria-label="Pagination" class="mt-12 flex items-center justify-between gap-4">
68
- {previous ? (
69
- <a href={previous} rel="prev" class="button button-secondary">
70
- Previous page
71
- </a>
72
- ) : (
73
- <span />
74
- )}
75
- {next && (
76
- <a href={next} rel="next" class="button button-secondary">
77
- Next page
78
- </a>
79
- )}
80
- </nav>
81
- )
82
- }
83
- </div>
84
- </Base>
13
+ <ListPage
14
+ locale={locale}
15
+ title={collection.name}
16
+ page={page.page}
17
+ lastPage={page.lastPage}
18
+ entries={page.entries.items}
19
+ pageUrl={(number) => urls.collection(collection, locale, number)}
20
+ translations={collectionAlternates(collection.id, urls)}
21
+ />
@@ -1,4 +1,4 @@
1
- import type { CollectionPage, HomepagePage } from '@rushcms/astro'
1
+ import type { CollectionPage, HomepagePage, TaxonomyPage } from '@rushcms/astro'
2
2
  import type { CollectionRef, Entry, LocaleCode, RushUrls } from '@rushcms/client'
3
3
  import GenericList from './collection.astro'
4
4
  import GenericEntry from './entry.astro'
@@ -11,6 +11,10 @@ export type ListViewProps = {
11
11
  page: CollectionPage
12
12
  }
13
13
 
14
+ export type TaxonomyViewProps = {
15
+ page: TaxonomyPage
16
+ }
17
+
14
18
  export type EntryViewProps = {
15
19
  entry: Entry
16
20
  locale: LocaleCode
@@ -0,0 +1,21 @@
1
+ ---
2
+ import { getUrls } from '@rushcms/astro'
3
+ import ListPage from '../components/list-page.astro'
4
+ import type { TaxonomyViewProps } from './index'
5
+
6
+ type Props = TaxonomyViewProps
7
+
8
+ const { page } = Astro.props
9
+ const { tag, locale } = page
10
+ const urls = getUrls(Astro)
11
+ ---
12
+
13
+ <ListPage
14
+ locale={locale}
15
+ title={tag.name}
16
+ page={page.page}
17
+ lastPage={page.lastPage}
18
+ entries={page.entries.items}
19
+ pageUrl={(number) => urls.taxonomy(tag, locale, number)}
20
+ translations={page.alternates}
21
+ />