feat: migrate website-creator from Next.js+Payload to Astro+Tina CMS
Major changes: - Replace Payload CMS with Tina CMS (self-hosted) - Add Astro DB for consent logging (PDPA compliant) - Update Tailwind v3 to v4 (@tailwindcss/vite plugin) - Add astro-tina-starter template - Rewrite consent template for Astro (ConsentBanner.astro, Astro DB, Nano Stores) - Add install-tina-backend.sh for self-hosted Tina per customer - Rename convert-astro.sh to migrate-tina.sh - Add AGENTS.md template for generated websites - Delete all Payload/Next.js files Technical updates: - Astro DB using defineDb with eq operators for queries - Tailwind v4 with @theme block - Tina CMS local development mode - Proper Astro API routes for consent Research-verified with official documentation (April 2026)
This commit is contained in:
@@ -142,7 +142,7 @@ Output:
|
||||
- meta_description: 150-160 chars
|
||||
- slug: Auto-generated (Thai-friendly)
|
||||
- images: Saved to website repo
|
||||
- astro_ready: true (content collections format)
|
||||
- payload_cms_ready: true (REST API format)
|
||||
```
|
||||
|
||||
**X/Twitter Thread:**
|
||||
@@ -415,55 +415,55 @@ def save_image_for_channel(image_data: bytes, topic: str, channel: str) -> str:
|
||||
### **Website-Creator Integration:**
|
||||
|
||||
```python
|
||||
def publish_blog_to_astro(article_md: str, website_repo: str) -> Dict:
|
||||
def publish_blog_to_payload(
|
||||
article_md: str,
|
||||
website_url: str,
|
||||
payload_token: str
|
||||
) -> Dict:
|
||||
"""
|
||||
Publish blog post to Astro content collections
|
||||
Returns deployment status
|
||||
Publish blog post to Payload CMS via REST API
|
||||
Returns publication status
|
||||
"""
|
||||
# Parse frontmatter
|
||||
frontmatter = parse_frontmatter(article_md)
|
||||
|
||||
|
||||
# Detect language
|
||||
lang = detect_content_language(article_md)
|
||||
|
||||
|
||||
# Generate slug
|
||||
slug = generate_slug(frontmatter['title'], lang)
|
||||
|
||||
# Determine output path
|
||||
output_path = os.path.join(
|
||||
website_repo,
|
||||
'src/content/blog',
|
||||
f'({lang})',
|
||||
f'{slug}.md'
|
||||
if lang == 'th':
|
||||
slug = f'th/{slug}'
|
||||
|
||||
# Convert markdown to Lexical JSON
|
||||
content = markdown_to_lexical(article_md)
|
||||
|
||||
# Prepare Payload document
|
||||
payload_doc = {
|
||||
'title': frontmatter['title'],
|
||||
'slug': slug,
|
||||
'content': content,
|
||||
'status': 'draft',
|
||||
'description': frontmatter.get('description', ''),
|
||||
}
|
||||
|
||||
# Send to Payload CMS API
|
||||
response = requests.post(
|
||||
f'{website_url}/api/posts',
|
||||
headers={'Authorization': f'Bearer {payload_token}'},
|
||||
json=payload_doc
|
||||
)
|
||||
|
||||
# Ensure directory exists
|
||||
os.makedirs(os.path.dirname(output_path), exist_ok=True)
|
||||
|
||||
# Write article
|
||||
with open(output_path, 'w', encoding='utf-8') as f:
|
||||
f.write(article_md)
|
||||
|
||||
# Copy images if any
|
||||
if 'images' in frontmatter:
|
||||
for img in frontmatter['images']:
|
||||
# Copy from temp location to website repo
|
||||
dest_path = os.path.join(website_repo, 'public', img['src'].lstrip('/'))
|
||||
os.makedirs(os.path.dirname(dest_path), exist_ok=True)
|
||||
shutil.copy(img['local_path'], dest_path)
|
||||
|
||||
# Git commit and push
|
||||
subprocess.run(['git', 'add', '.'], cwd=website_repo, check=True)
|
||||
subprocess.run(['git', 'commit', '-m', f'Add blog post: {slug}'], cwd=website_repo, check=True)
|
||||
subprocess.run(['git', 'push', 'origin', 'main'], cwd=website_repo, check=True)
|
||||
|
||||
# Return deployment info
|
||||
|
||||
result = response.json()
|
||||
|
||||
# Return publication info
|
||||
return {
|
||||
'published': True,
|
||||
'id': result.get('id'),
|
||||
'slug': slug,
|
||||
'language': lang,
|
||||
'path': output_path,
|
||||
'deployment_url': f"https://your-domain.com/blog/{slug}" if lang == 'en' else f"https://your-domain.com/th/{slug}"
|
||||
'admin_url': f'{website_url}/admin/collections/posts/{result.get("id")}',
|
||||
'api_url': f'{website_url}/api/posts',
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
Reference in New Issue
Block a user