- Change Dockerfile from nginx (static) to Node.js (SSR) - Add @astrojs/node adapter for SSR mode - Add OUT_DIR=/data for persistent SQLite storage - Add .env.example with persistent storage config - Update README with Easypanel deployment instructions - Database persists across redeployments at /data/astro.db
Astro Tina Starter
Astro 6.1.7 + Tina CMS starter template with Tailwind CSS 4.x
Tech Stack
- Framework: Astro 6.1.7 (SSR mode)
- CMS: Tina CMS (self-hosted)
- Styling: Tailwind CSS 4.x with
@tailwindcss/vite - Database: Astro DB (LibSQL/SQLite)
- Adapter: @astrojs/node (SSR)
- State: Nano Stores + React
- Language: TypeScript
Features
- Self-hosted Tina CMS with schema-based content
- Tailwind CSS 4.x using
@tailwindcss/viteplugin - Astro DB for consent logging (PDPA compliant)
- SSR mode for API routes
- Docker-ready with persistent storage
- Thai language support foundation
Quick Start
# Install dependencies
npm install
# Start development
npm run dev
# Build for production
npm run build
Tina CMS Access
During development, access Tina CMS at:
For production, you'll need a TINA_TOKEN environment variable.
Easypanel Deployment
This template is designed for Easypanel with persistent volume support.
Important: Persistent Storage
Astro DB stores SQLite at /data/ - this directory is mounted as a persistent volume in Easypanel.
When deploying:
- Set environment variable
OUT_DIR=/data - Mount persistent volume to
/datain Easypanel - Database will persist across redeployments
Environment Variables
# Required for persistent storage
OUT_DIR=/data
# Optional - Tina CMS
TINA_TOKEN=your-tina-token
# Optional - External database (instead of local SQLite)
# TURSO_DATABASE_URL=libsql://your-db.turso.io
# TURSO_AUTH_TOKEN=your-auth-token
Easypanel Setup
- Create new service from Git repo
- Set build command:
npm run build - Set start command:
node dist/server/entry.mjs - Add environment variable:
OUT_DIR=/data - Mount persistent volume to
/data
Project Structure
astro-tina-starter/
├── .tina/
│ ├── config.ts # Tina CMS configuration
│ └── schema.ts # Content schema definitions
├── db/
│ ├── config.ts # Astro DB schema (consent logs)
│ └── seed.ts # Database seed script
├── src/
│ ├── styles/
│ │ └── global.css # Tailwind v4 styles
│ ├── layouts/
│ │ └── Layout.astro
│ ├── pages/
│ │ ├── index.astro
│ │ └── api/ # API routes (consent, etc.)
│ ├── components/
│ │ └── Header.astro
│ └── content/
│ └── config.ts # Tina content collections
├── Dockerfile # Multi-stage Node.js (not nginx)
└── package.json
Tailwind CSS 4.x
This template uses Tailwind CSS 4.x with the @tailwindcss/vite plugin.
The configuration is done via CSS @theme block in src/styles/global.css.
@import "tailwindcss";
@theme {
--color-primary: #1a1a1a;
--color-accent: #3b82f6;
}
Astro DB
The template includes a consent-log table for PDPA compliance:
// db/config.ts
import { defineDb, defineTable, column } from 'astro:db';
const ConsentLog = defineTable({
columns: {
id: column.number({ primaryKey: true }),
action: column.text(),
purpose: column.text(),
analytics: column.boolean({ default: false }),
marketing: column.boolean({ default: false }),
functional: column.boolean({ default: false }),
userAgent: column.text({ optional: true }),
ip: column.text({ optional: true }),
timestamp: column.date(),
sessionId: column.text({ optional: true }),
},
});
export default defineDb({ tables: { ConsentLog } });
Database file location: /data/astro.db (persistent across redeployments)
License
MIT