Add content collections, layouts and blog pages for Tina integration

This commit is contained in:
Kunthawat Greethong
2026-04-28 13:18:16 +07:00
parent 484d7d1e28
commit 7420e02a84
9 changed files with 257 additions and 5 deletions

5
.gitignore vendored
View File

@@ -1,4 +1,7 @@
node_modules
dist
.env
*.log
*.log
.astro
package-lock.json
.omc

View File

@@ -1,12 +1,19 @@
{
"name": "astro6-simple",
"name": "astro-tina",
"type": "module",
"scripts": {
"dev": "astro dev --host 0.0.0.0",
"build": "astro build",
"preview": "astro preview"
"preview": "astro preview",
"dev:tina": "tinacms dev -c \"node ./tina/config.server.ts\""
},
"dependencies": {
"astro": "^6.1.7"
"astro": "^5.6.1",
"@astrojs/mdx": "^4.0.8",
"@tinacms/cli": "^2.2.3",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"tinacms": "^2.2.3",
"astro-tina": "^0.1.4"
}
}
}

22
src/content.config.ts Normal file
View File

@@ -0,0 +1,22 @@
import { defineCollection, z } from "astro:content"
const postCollection = defineCollection({
type: "content",
schema: z.object({
title: z.string(),
description: z.string().optional(),
}),
})
const pageCollection = defineCollection({
type: "content",
schema: z.object({
title: z.string(),
description: z.string().optional(),
}),
})
export const collections = {
posts: postCollection,
pages: pageCollection,
}

View File

@@ -0,0 +1,8 @@
---
title: About
description: About our site
---
# About Us
We are building modern websites with Astro and Tina CMS.

View File

@@ -0,0 +1,17 @@
---
title: Welcome to Astro + Tina
description: A modern starter with Astro 6 and Tina CMS
---
# Welcome to Astro + Tina
This is a sample page managed by Tina CMS.
## Features
- Visual content editing with Tina CMS
- Git-based content management
- Static site generation with Astro
- Easy deployment on Easypanel
Stay tuned for more updates!

View File

@@ -0,0 +1,5 @@
{
"siteName": "Astro Tina Starter",
"siteDescription": "A modern starter template with Astro 6, Tina CMS, and Thai language support.",
"language": "th"
}

71
src/layouts/Layout.astro Normal file
View File

@@ -0,0 +1,71 @@
---
const { title, description } = Astro.props
---
<!DOCTYPE html>
<html lang="th">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="description" content={description || "Astro 6 + Tina CMS starter template"} />
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
<title>{title || "Astro Tina Starter"}</title>
<style>
body {
font-family: system-ui, sans-serif;
line-height: 1.6;
margin: 0;
padding: 0;
background: #f8fafc;
color: #0f172a;
}
main {
padding: 4rem 1.5rem;
max-width: 64rem;
margin: 0 auto;
}
h1 {
font-size: 3rem;
font-weight: 700;
letter-spacing: -0.025em;
margin-bottom: 1.5rem;
}
p {
font-size: 1.125rem;
color: #475569;
margin-bottom: 2rem;
max-width: 42rem;
}
.grid {
display: grid;
gap: 1.5rem;
}
@media (min-width: 768px) {
.grid {
grid-template-columns: repeat(2, 1fr);
}
}
.card {
padding: 1.5rem;
background: white;
border-radius: 0.75rem;
border: 1px solid #e2e8f0;
}
.card h2 {
font-size: 1.25rem;
font-weight: 600;
margin-bottom: 0.75rem;
}
.card p {
font-size: 1rem;
color: #475569;
margin: 0;
}
</style>
</head>
<body>
<main data-astro-cid-sckkx6r4>
<slot />
</main>
<script src="https://consent.moreminimore.com/consent-loader.js" data-site-id="demo" data-api-base="https://consent.moreminimore.com"></script>
</body>
</html>

57
src/pages/blog.astro Normal file
View File

@@ -0,0 +1,57 @@
---
import { getCollection } from 'astro:content'
import Layout from "../layouts/Layout.astro"
const posts = await getCollection('posts')
---
<Layout title="Blog">
<main>
<h1>Blog Posts</h1>
<div class="posts">
{posts.map(post => (
<article class="post">
<h2><a href={`/posts/${post.slug}`}>{post.data.title}</a></h2>
{post.data.description && <p>{post.data.description}</p>}
</article>
))}
</div>
</main>
</Layout>
<style>
main {
max-width: 64rem;
margin: 0 auto;
padding: 4rem 1.5rem;
}
h1 {
font-size: 2.5rem;
margin-bottom: 2rem;
}
.posts {
display: flex;
flex-direction: column;
gap: 2rem;
}
.post {
padding: 1.5rem;
background: white;
border-radius: 0.75rem;
border: 1px solid #e2e8f0;
}
.post h2 {
font-size: 1.5rem;
margin-bottom: 0.5rem;
}
.post h2 a {
color: inherit;
text-decoration: none;
}
.post h2 a:hover {
color: #2563eb;
}
.post p {
color: #475569;
margin: 0;
}
</style>

View File

@@ -0,0 +1,62 @@
---
import { getCollection } from 'astro:content'
import Layout from "../../layouts/Layout.astro"
export async function getStaticPaths() {
const posts = await getCollection('posts')
return posts.map(post => ({
params: { slug: post.slug },
props: { post },
}))
}
const { post } = Astro.props
const { Content } = await post.render()
---
<Layout title={post.data.title} description={post.data.description}>
<main>
<a href="/blog" class="back">← Back to Blog</a>
<article>
<h1>{post.data.title}</h1>
<Content />
</article>
</main>
</Layout>
<style>
main {
max-width: 64rem;
margin: 0 auto;
padding: 4rem 1.5rem;
}
.back {
display: inline-block;
margin-bottom: 2rem;
color: #2563eb;
text-decoration: none;
}
.back:hover {
text-decoration: underline;
}
article h1 {
font-size: 2.5rem;
margin-bottom: 1.5rem;
}
article :global(p) {
line-height: 1.8;
margin-bottom: 1.5rem;
}
article :global(h2) {
font-size: 1.5rem;
margin-top: 2rem;
margin-bottom: 1rem;
}
article :global(ul) {
margin-bottom: 1.5rem;
padding-left: 1.5rem;
}
article :global(li) {
margin-bottom: 0.5rem;
}
</style>