Add library feature (#1)

Co-authored-by: Aaron Yarborough <3855819+AaronJY@users.noreply.github.com>
Reviewed-on: #1
This commit is contained in:
Aaron Yarborough 2025-03-29 11:44:02 +00:00
parent 5a28e13e51
commit 205522acc9
48 changed files with 13286 additions and 1165 deletions

4
.gitignore vendored
View file

@ -35,4 +35,6 @@ yarn-error.log*
*.tsbuildinfo
next-env.d.ts
deploy-vars.sh
deploy-vars.sh
node_modules
.env

10
content/books/1984.md Normal file
View file

@ -0,0 +1,10 @@
---
title: '1984'
author: George Orwell
stars: 3
readDate: 2023-07-31T23:00:00.000Z
url: 'https://app.thestorygraph.com/books/6ff3f487-8d37-4ac5-8190-6622d6562639'
thumbnailUrl: 'https://cdn.thestorygraph.com/v43bj24inkwioiogb5uz8nqmpnpw'
tags: 'fiction, dystopian, classics'
---

View file

@ -0,0 +1,10 @@
---
title: A Monster Calls
author: Patrick Ness
stars: 4
readDate: 2024-05-31T23:00:00.000Z
url: 'https://app.thestorygraph.com/books/170c1204-1410-4246-babb-c80e31aebea9'
thumbnailUrl: 'https://cdn.thestorygraph.com/50qkuazqx2lidfd0hk74ltifz9nf'
tags: 'fiction, young adult'
---

View file

@ -0,0 +1,10 @@
---
title: Diary of An Oxygen Thief
author: Anonymous
stars: 4
readDate: 2024-03-01T00:00:00.000Z
url: 'https://app.thestorygraph.com/books/9ce581f2-d9ac-4be1-abf7-4597684bab7f'
thumbnailUrl: 'https://cdn.thestorygraph.com/l5zkpt8v2wj76ri6nkq7ismqsskl'
tags: 'romance, fiction'
---

View file

@ -0,0 +1,10 @@
---
title: No God But God
author: Reza Aslan
stars: 4
readDate: 2023-01-01T00:00:00.000Z
url: 'https://app.thestorygraph.com/books/27cb3f11-77c6-4eca-9344-d64885e6f1c4'
thumbnailUrl: 'https://cdn.thestorygraph.com/gf3c92roqrgdbdsgphns5n111t93'
tags: 'non-fiction, religion, history'
---

View file

@ -0,0 +1,10 @@
---
title: Sex & Punishment
author: Eric Berkowitz
stars: 3
readDate: 2024-05-31T23:00:00.000Z
url: 'https://app.thestorygraph.com/books/79ffd129-2325-45d0-826d-c6969a09e239'
thumbnailUrl: 'https://cdn.thestorygraph.com/lqtuj9d7fdj1qw1lei01yby42h9z'
tags: 'non-fiction, history'
---

View file

@ -0,0 +1,10 @@
---
title: The Nature of Alexander
author: Mary Renault
stars: 4.5
readDate: 2023-03-31T23:00:00.000Z
url: 'https://app.thestorygraph.com/books/bc111e8b-1b3f-466a-9efd-c3316ae4b533'
thumbnailUrl: 'https://cdn.thestorygraph.com/68zjkhp67u2bi6qh3melbyqaly06'
tags: 'non-fiction, history, biography'
---

View file

@ -0,0 +1,10 @@
---
tags: 'non-fiction, classics, history'
title: A Night To Remember
author: Walter Lord
stars: 3.5
readDate: 2024-06-30T23:00:00.000Z
url: 'https://app.thestorygraph.com/books/5192ee9e-ffb2-4c72-a7c3-8051d950d66f'
thumbnailUrl: 'https://cdn.thestorygraph.com/pdwshwni6jyc7ivp55j6tsxzngfl'
---

View file

@ -0,0 +1,10 @@
---
title: Alice's Adventures in Wonderland
author: Lewis Carroll
stars: 3
readDate: 2023-04-30T23:00:00.000Z
url: 'https://app.thestorygraph.com/books/83b0e44a-06fe-4042-9d2d-e4f41244fb9c'
thumbnailUrl: 'https://cdn.thestorygraph.com/l83t3e6wh6tq7dqxbvrba34ee2nb'
tags: 'fiction, classics, fantasy'
---

View file

@ -0,0 +1,10 @@
---
title: Animal Farm
author: George Orwell
stars: 4
readDate: 2023-01-01T00:00:00.000Z
url: 'https://app.thestorygraph.com/books/f4b706d9-4ed9-4b15-85e0-2493581de818'
thumbnailUrl: 'https://cdn.thestorygraph.com/jztibk5xvnynw7mh7hfw0orhbzuh'
tags: 'fiction, classics, dystopian'
---

View file

@ -0,0 +1,10 @@
---
title: Cities That Shaped The Ancient World
author: John Julius Norwich
stars: 3.5
readDate: 2023-02-01T00:00:00.000Z
url: 'https://app.thestorygraph.com/books/20bc1ff4-56bb-4e88-a403-bc150d45f9d2'
thumbnailUrl: 'https://cdn.thestorygraph.com/i8znw2yrd6p4m76dx6rvyuyd48h2'
tags: 'non-fiction, history'
---

View file

@ -0,0 +1,11 @@
---
title: The Song of Achilles
author: Madline Miller
stars: 2.5
readDate: 2025-03-22T00:00:00.000Z
url: 'https://app.thestorygraph.com/books/9202845d-26cd-4a85-b15f-408116117028'
thumbnailUrl: 'https://cdn.thestorygraph.com/m8cw3kb3qx4h2jl8kg0u4m3txhie'
tags: 'fiction, fantasy, romance'
---
This one really tailed off half-way through. I found the characters very one-dimensional (Patrcolus pines after Achilles, Achilles has muscles and can swing a sword fast), but the story took me at least up until the half-way mark. Weirdly I wasn't interested too much when the actual Iliad story line started to get going - maybe because I've heard it a million times before - and their essentially non-existent romance (more accurately an inch-deep obsession, I'd argue) didn't exactly inspire me to carry on reading.

View file

@ -0,0 +1,10 @@
---
title: Star Maker
author: Olaf Stapledon
stars: 4.5
readDate: 2023-03-01T00:00:00.000Z
url: 'https://app.thestorygraph.com/books/c1d60727-8e24-4a1f-9f0e-974d68a934d2'
thumbnailUrl: 'https://cdn.thestorygraph.com/bln6q5k1v7ealnwss4msv0jixlhk'
tags: 'fiction, classics, science fiction'
---

View file

@ -0,0 +1,10 @@
---
title: 'Stasiland: Stories from Behind the Berlin Wall'
author: Anna Funder
stars: 4
readDate: 2023-02-01T00:00:00.000Z
url: 'https://app.thestorygraph.com/books/9202845d-26cd-4a85-b15f-408116117028'
thumbnailUrl: 'https://cdn.thestorygraph.com/gphzjvwbhr8d5agrieobx0yy2xhb'
tags: 'non-fiction, history, politics'
---

View file

@ -0,0 +1,10 @@
---
title: Stray Reflections
author: Muhammad Iqbal
stars: 5
readDate: 2023-03-01T00:00:00.000Z
url: null
thumbnailUrl: null
tags: 'non-fiction, politics, philosophy'
---

View file

@ -0,0 +1,10 @@
---
title: The Marmalade Diaries
author: Ben Aitken
stars: 4.5
readDate: 2023-01-01T00:00:00.000Z
url: 'https://app.thestorygraph.com/books/406fe719-07de-44ba-b4e7-86714f638cf9'
thumbnailUrl: 'https://cdn.thestorygraph.com/ou589mae0cxxup4cqq1mlnqdaj62'
tags: non-fiction
---

View file

@ -0,0 +1,10 @@
---
title: The Midnight Library
author: Matt Haig
stars: 4
readDate: 2024-06-30T23:00:00.000Z
url: 'https://app.thestorygraph.com/books/d9c7ed04-6148-4e01-a118-d96cba16f507'
thumbnailUrl: 'https://cdn.thestorygraph.com/b9g1h8bhrqz7qs2fagzhsixbp6xy'
tags: 'fiction, literary, science fiction'
---

View file

@ -0,0 +1,11 @@
---
title: 'To Be Taught, If Fortunate'
author: Becky Chambers
stars: 4.5
readDate: 2025-03-22T00:00:00.000Z
url: 'https://app.thestorygraph.com/books/fca2631f-b3e2-4b9d-a2fd-4c1ec5e4d3f7'
thumbnailUrl: 'https://cdn.thestorygraph.com/8ep9zjc581zefkzfyhtizqjnz8u5'
tags: 'fiction, science fiction'
---
Really enjoyed this! It was reflective yet lighthearted. I also love this specific flavour of sci-fi, where vastly different species of aliens and worlds are thought up and articulated beautifully by the author.

View file

@ -0,0 +1,11 @@
---
title: When the Moon Hits Your Eye
author: John Scalzi
stars: 2.5
readDate: 2025-03-26T00:00:00.000Z
url: 'https://app.thestorygraph.com/books/4f3c3b02-3d2b-4765-93ac-4656133bbec5'
thumbnailUrl: 'https://cdn.thestorygraph.com/718cb49yqfu02zekeq22yl8lgm8v'
tags: 'fiction, science fiction'
---
Some interesting chapters in here exploring how governments and various public/private institutions could deal with the moon randomly turning to choose, but a lot of fluff in between them. Can't really recommend, unless you want to skip to the good bits like I did.

View file

@ -2,7 +2,9 @@
title: Attitudes to reading, and how mine have changed
pubdate: 2025-03-18T00:00:00.000Z
desc: I was discussing reading habits with my good friend Beth, specifically around reading multiple books at once vs. reading a single book at a time...
tags: reading, books
tags:
- reading
- books
---
I was discussing reading habits with my good friend Beth, specifically around reading multiple books at once vs. reading a single book at a time (we're both very members of the former group), and it got me thinking as to why there seems to me to be this split in reading habits, and where it might come from.

View file

@ -2,7 +2,9 @@
title: Migrating from GitHub to Forgejo
pubdate: 2025-03-16T00:00:00.000Z
desc: I recently moved all of my reposfrom GitHub to a self-hosted Forgejo instance running on my own servers.
tags: tech, hosting
tags:
- tech
- hosting
---
I recently moved all of my repos (public and private) from GitHub to a self-hosted [Forgejo](https://forgejo.org/) instance running on my own servers.

View file

@ -3,7 +3,10 @@ title: Performance considerations when writing a TCP game server in dotnet
pubdate: 2025-02-23T21:12:37.864Z
moddate: 2025-03-21T21:12:47.864Z
desc: While writing a TCP game server in dotnet for a hobby project, I learned a few ways to improve the efficiency and scalability of the server while running into some performance issues. Here's what I learned!
tags: tech, programming, dotnet
tags:
- tech
- programming
- dotnet
---
While writing a TCP game server in dotnet for a hobby project (check it out [here](https://github.com/AaronJY/GServer)), I learned a few ways to improve the efficiency and scalability of the server while running into some performance issues.

View file

@ -2,7 +2,9 @@
title: "Quickwrite: A reflection on Wintering by Katherine May"
pubdate: 2025-03-09T00:00:00.000Z
desc: "Katherine May draws a unique parallel in her book Wintering between the coming of and living through the winter months, and those liminal times in your life when a gap opens up underfoot and swallows us whole...."
tags: books, reading
tags:
- books
- reading
---
Katherine May draws a unique parallel in her book Wintering between the coming of and living through the winter months, and those liminal times in your life when a gap opens up underfoot and swallows us whole. Its never clear when such a gap appears to steal us away, and how long exactly well spend in the liminality we fall into, and most of us claw at the walls in an attempt to scale up and out, back into the warm light of day how things used to be. Katherines book is an account of how she learned to see it more as a wave to ride than a locked room to break free from. Her ultimate message is an argument to reframe it, or to see it for what it really is; not as a bleak, timeless realm devoid of hope and light, but of a necessary state we all find ourselves in at various points in our lives, and that this realm offers its own medicines for those who care to look. These seasonal and spiritual changes Katherine refers to as Wintering aptly a verb to articulate its ephemeral nature serve much in the same way a good nights sleep does: while a deep and peaceful sleep purges metabolic waste and toxins from our brains, a wintering can offer a more spiritual cleanse; a hibernation after a hot and unrelenting summer; a mirror held up in front to break our blind and frenzied sprint towards a goal weve long forgotten; a beloved teacher from our school days with a soft voice, reassuring smile and placations to calm our nerves.

View file

@ -2,7 +2,9 @@
title: Deploying aaronjy.me on a Google Storage bucket
pubdate: 2024-05-01T00:00:00.000Z
desc: "Google Cloud Storage is an effective solution for hosting static sites, offering a simple and scalable way to manage web assets. A manual deployment strategy involves four key steps: backing up existing files to a backup bucket, removing sensitive files for security, uploading the latest site files from the build directory, and invalidating Googles global cache to ensure users access updated content."
tags: tech, hosting
tags:
- tech
- hosting
---
Google actually has [documentation](https://cloud.google.com/storage/docs/hosting-static-website) on how to deploy a static site to a storage bucket, but I wanted to talk about how I handle deployments, as Google doesn't covert that!

View file

@ -2,7 +2,8 @@
title: Supporting content file structure changes on a static site
pubdate: 2024-03-18T16:47:32.150Z
desc: Static site generators (SSGs) convert complex site sources into HTML, CSS, and JS, allowing flexible hosting options. While they offer benefits like speed and low costs, updating content can be challenging for non-technical users. A solution involves assigning unique identifiers to articles and creating a URL mapping file to simplify restructuring and managing content links.
tags: tech
tags:
- tech
---
Static site generators (SSGs) are great. They take your complex site source and distil it down to the web's native language: HTML, CSS and JS. You can host your files anywhere: in cloud-native storage buckets; on low-cost CPanel hosting; on global CDNs; your old Lenovo ThinkPad in your cupboard running an Apache server that hasn't been patched since 2008; the list goes on. Wanna go further and throw away your CMS? Cool, you can use markdown files and a text editor as your CMS.

View file

@ -2,7 +2,10 @@
const nextConfig = {
reactStrictMode: true,
output: 'export',
trailingSlash: true // ensure pages get their own directory in output
trailingSlash: true, // ensure pages get their own directory in output
images: {
unoptimized: true
}
}
export default nextConfig

13833
package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -1,10 +1,10 @@
{
"name": "www-aaronjy-2024",
"version": "1.6.3.0",
"name": "www-aaronjy-me",
"version": "1.7.0.0",
"private": true,
"type": "module",
"scripts": {
"dev": "next dev",
"dev": "TINA_PUBLIC_IS_LOCAL=true tinacms dev -c \"next dev\"",
"build": "next build",
"postbuild": "next-sitemap --config next-sitemap.config.cjs",
"start": "next start",
@ -14,16 +14,21 @@
"test": "jest --verbose --passWithNoTests",
"lint": "next lint"
},
"standard": {
"ignore": [
"/tina/**/*"
]
},
"dependencies": {
"@highlightjs/cdn-assets": "^11.11.1",
"date-fns": "^4.1.0",
"feather-icons": "^4.29.2",
"highlight.js": "^11.11.0",
"next": "^14.2.6",
"next-seo": "^6.5.0",
"react": "^18",
"react-dom": "^18"
},
"react-dom": "^18",
"tinacms": "^2.7.3"
},
"devDependencies": {
"@babel/core": "^7.24.0",
"@babel/preset-env": "^7.25.4",
@ -32,6 +37,7 @@
"@commitlint/config-conventional": "^19.1.0",
"@testing-library/jest-dom": "^6.4.2",
"@testing-library/react": "^16.0.0",
"@tinacms/cli": "^1.9.3",
"@types/jest": "^29.5.12",
"babel-jest": "^29.7.0",
"eslint": "^9.9.0",

2
public/admin/.gitignore vendored Normal file
View file

@ -0,0 +1,2 @@
index.html
assets/

Binary file not shown.

After

Width:  |  Height:  |  Size: 78 KiB

View file

@ -0,0 +1,48 @@
import { formatDate } from '@/lib/helpers'
import { NextSeo } from 'next-seo'
import Image from 'next/image'
import Link from 'next/link'
import React from 'react'
import style from './Book.module.css'
import ExternalLink from '../ExternalLink/ExternalLink'
function Book ({ attributes, html }) {
return (
<>
<h1>{attributes.title}<br /><small>by {attributes.author}</small></h1>
<Link href='./'>Back...</Link>
<article>
<NextSeo
title={attributes.title} description={attributes.desc} openGraph={
{
title: attributes.title,
description: attributes.desc,
type: 'article',
article: {
publishedTime: attributes.pubdate ?? null
}
}
}
/>
<div>
<div className={style.layout}>
<Image src={attributes.thumbnailUrl} width={250} height={580} alt='' className={style.thumbnail} />
<div>
<div data-test='content' dangerouslySetInnerHTML={{ __html: html || '<p>(no review)</p>' }} />
<p>
<span className='bold'>Rating:</span>&nbsp;{attributes.stars}/5<br />
<span className='bold'>Read on:</span>&nbsp;{formatDate(attributes.readDate)}
</p>
<p><ExternalLink href={attributes.url}>View on The StoryGraph</ExternalLink></p>
</div>
</div>
</div>
</article>
</>
)
}
export default Book

View file

@ -0,0 +1,34 @@
.layout {
display: flex;
flex-direction: row;
gap: 1.25rem;
margin: 1.25rem 0;
}
.layout:first-child {
flex-grow: 0;
flex-shrink: 0;
}
.layout:last-child {
flex-grow: 1;
}
.layout p:first-child {
margin-top: 0;
}
.thumbnail {
border-radius: 8px;
}
@media screen and (max-width: 650px) {
.layout {
flex-direction: column-reverse;
}
.thumbnail {
width: 100%;
}
}

View file

@ -0,0 +1,24 @@
import style from './BookListItem.module.css'
import Link from 'next/link'
export default function BookListItem ({ href, title, author, stars, readDate, url, thumbnailUrl, tags, review }) {
return (
<div className={style.item}>
<Link href={href}>
<div
className={style.thumb} style={{
backgroundImage: `url(${thumbnailUrl ?? '/img/book-placeholder.jpg'})`
}}
/>
</Link>
<div>
<h2 className={style.heading}>
<Link href={href}>{title}</Link>
</h2>
<p className={style.author}>{author}</p>
<p>{tags}</p>
{/* <p>{stars}/5</p> */}
</div>
</div>
)
}

View file

@ -0,0 +1,26 @@
.item {
height: 100%;
display: flex;
flex-direction: column;
flex-grow: 1;
}
.heading {
font-size: 1rem;
margin-bottom: 5px;
}
.author {
margin-top: 5px;
/* font-weight: bold; */
}
.thumb {
width: auto;
height: 290px;
background-position: center;
background-repeat: no-repeat;
background-size: cover;
border-radius: 6px;
}

View file

@ -0,0 +1,11 @@
import style from './Grid.module.css'
export default function Grid ({ columns, children }) {
return (
<div
className={style.grid}
>
{children}
</div>
)
}

View file

@ -0,0 +1,5 @@
.grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(140px, 1fr));
gap: 1rem;
}

View file

@ -11,6 +11,7 @@ function Header () {
<Link href='/writing'>Writing</Link>{', '}
<Link href='/tags'>Tags</Link>{', '}
<Link href='/cv'>CV</Link>{', '}
<Link href='/library'>Library</Link>{', '}
<Link href='/about'>About</Link>
</nav>
</header>

View file

@ -1,7 +1,7 @@
import { formatDate } from '@/lib/helpers'
import Link from 'next/link'
export default function StaticContentList ({ entries, urlPrefix }) {
export default function StaticContentList ({ entries, urlPrefix, max = 0 }) {
return (
<table>
<tbody>
@ -12,7 +12,7 @@ export default function StaticContentList ({ entries, urlPrefix }) {
<Link href={`${urlPrefix}${e.slug}`}>{e.attributes.title}</Link>
</td>
</tr>
))}
)).slice(0, max > 0 ? max : entries.length)}
</tbody>
</table>
)

View file

@ -56,8 +56,6 @@ export function getStaticEntries (contentPath) {
const directoryItems = fs.readdirSync(contentPath, { withFileTypes: true })
return directoryItems.map((dirent) =>
getMarkdownEntry(`${dirent.path}/${dirent.name}`)
).sort((a, b) =>
new Date(b.attributes.pubdate).getTime() - new Date(a.attributes.pubdate).getTime()
)
}
@ -68,8 +66,7 @@ export function getContentTags (contentPath) {
for (const entry of entries) {
if (!entry.attributes.tags) { continue }
const tags = entry.attributes.tags.split(', ')
const tags = entry.attributes.tags
for (const tag of tags) {
allTags[tag] = !allTags[tag] ? 1 : allTags[tag] + 1
}

View file

@ -7,3 +7,13 @@ export function toSlug (input) {
export function formatDate (date) {
return dateFns.format(Date.parse(date), 'PPP')
}
/**
* Silliness to make sure dates don't get passed to the
* page function below as [object Object]
* @param {*} obj
* @returns
*/
export function stringifyAndParse (obj) {
return JSON.parse(JSON.stringify(obj))
}

View file

@ -33,7 +33,7 @@ export default function Home ({ postEntries }) {
<section>
<h2>Recent posts</h2>
<StaticContentList entries={postEntries} urlPrefix='writing/' />
<StaticContentList entries={postEntries} urlPrefix='writing/' max={5} />
</section>
</DefaultLayout>

View file

@ -0,0 +1,17 @@
import React from 'react'
import DefaultLayout from '@/layouts/DefaultLayout/DefaultLayout'
import { getStaticEntryPaths, getStaticEntryProps } from '@/lib/content'
import Book from '@/components/Book/Book'
import { stringifyAndParse } from '@/lib/helpers'
export const getStaticPaths = () => getStaticEntryPaths('./content/books')
export const getStaticProps = (ctx) =>
stringifyAndParse(getStaticEntryProps('./content/books', ctx))
export default function LibrarySingle ({ attributes, html }) {
return (
<DefaultLayout>
<Book attributes={attributes} html={html} />
</DefaultLayout>
)
}

View file

@ -0,0 +1,46 @@
import BookListItem from '@/components/BookListItem/BookListItem'
import Grid from '@/components/Grid/Grid'
import DefaultLayout from '@/layouts/DefaultLayout/DefaultLayout'
import { getStaticEntries } from '@/lib/content'
import { stringifyAndParse } from '@/lib/helpers'
import { NextSeo } from 'next-seo'
export const Title = 'Library'
export const getStaticProps = () => {
const bookEntries = getStaticEntries('./content/books')
.sort((a, b) => {
return b.attributes.readDate - a.attributes.readDate
})
return {
props: {
bookEntries: stringifyAndParse(bookEntries)
}
}
}
export default function Library ({ bookEntries }) {
return (
<DefaultLayout>
<NextSeo
title={Title}
openGraph={
{
title: Title
}
}
/>
<h1>{Title}</h1>
<section>
<Grid columns={5}>
{bookEntries.map((entry, _) => (
<BookListItem key={entry.attributes.title} {...entry.attributes} href={`/library/${entry.slug}`} />
))}
</Grid>
</section>
</DefaultLayout>
)
}

View file

@ -7,6 +7,9 @@ import StaticContentList from '@/components/StaticContentList/StaticContentList'
export const getStaticProps = () => ({
props: {
postEntries: getStaticEntries('./content/writing')
.sort((a, b) =>
new Date(b.attributes.pubdate).getTime() - new Date(a.attributes.pubdate).getTime()
)
}
})

View file

@ -13,4 +13,12 @@ tr {
td:first-child {
padding-right: 20px;
}
.form-group {
margin: 20px 0;
}
.bold {
font-weight: 700;
}

1
tina/.gitignore vendored Normal file
View file

@ -0,0 +1 @@
__generated__

136
tina/config.js Normal file
View file

@ -0,0 +1,136 @@
import { defineConfig } from 'tinacms'
// Your hosting provider likely exposes this as an environment variable
const branch =
process.env.GITHUB_BRANCH ||
process.env.VERCEL_GIT_COMMIT_REF ||
process.env.HEAD ||
'main'
export default defineConfig({
branch,
// Get this from tina.io
clientId: process.env.NEXT_PUBLIC_TINA_CLIENT_ID,
// Get this from tina.io
token: process.env.TINA_TOKEN,
build: {
outputFolder: 'admin',
publicFolder: 'public'
},
media: {
tina: {
mediaRoot: '',
publicFolder: 'public'
}
},
// See docs on content modeling for more info on how to setup new content models: https://tina.io/docs/schema/
schema: {
collections: [
{
name: 'books',
label: 'Library',
path: 'content/books',
match: {
include: '*'
},
format: 'md',
fields: [
{
type: 'string',
name: 'title',
label: 'Title',
isTitle: true,
required: true
},
{
type: 'string',
name: 'author',
label: 'Author',
required: true
},
{
type: 'number',
name: 'stars',
label: 'Stars',
required: true
},
{
type: 'datetime',
name: 'readDate',
label: 'Read date',
required: false
},
{
type: 'string',
name: 'url',
label: 'URL',
required: false
},
{
type: 'string',
name: 'thumbnailUrl',
label: 'Thumbnail URL',
required: false
},
{
type: 'string',
name: 'tags',
label: 'Tags',
required: true
},
{
type: 'rich-text',
name: 'body',
label: 'Body',
isBody: true
}
]
},
{
name: 'writing',
label: 'Writing',
path: 'content/writing',
match: {
include: '*'
},
format: 'md',
fields: [
{
type: 'string',
name: 'title',
label: 'Title',
isTitle: true,
required: true
},
{
type: 'datetime',
name: 'pubdate',
label: 'Publish Date'
},
{
type: 'string',
ui: {
component: 'textarea'
},
name: 'desc',
label: 'Description'
},
{
type: 'string',
name: 'tags',
label: 'Tags',
list: true
},
{
type: 'rich-text',
name: 'body',
label: 'Body',
isBody: true
}
]
}
]
}
})

1
tina/tina-lock.json Normal file

File diff suppressed because one or more lines are too long