Files
Cozy-Den/DEVELOPMENT.md
T
Latte 077cc06d75
CI / ci (push) Successful in 26s
CI / ci (pull_request) Successful in 27s
Docker / docker (pull_request) Successful in 15s
Enterprise AI Code Review / ai-review (pull_request) Successful in 1m53s
Security / security (pull_request) Successful in 6s
Add blog via Astro content collections
Introduce blog support: content collection schema, listing and post
routes, and a sample Markdown post. Update docs and TODO; add blog
assets dir and adjust color variables in docs. Also set
absolute_redirect off in nginx.conf for container routing.
2026-03-02 19:13:30 +01:00

9.2 KiB

Cozy Den - Developer Documentation

Project Overview

Cozy Den is a landing page for hiddenden.cafe built with Astro. The site features a warm, cozy aesthetic inspired by coffee shops and hidden dens, representing values of privacy, self-hosting, and open-source software.

Tech Stack:

  • Astro 4.x (Static Site Generator)
  • TypeScript (strict mode)
  • Vanilla CSS with CSS Custom Properties
  • Docker + Nginx for deployment
  • Node.js 18+

Project Structure

cozy-den/
├── src/
│   ├── content/
│   │   ├── config.ts              # Content collection schema
│   │   └── blog/
│   │       └── *.md               # Blog posts (Markdown)
│   ├── layouts/
│   │   └── BaseLayout.astro      # Base HTML layout with global styles
│   ├── pages/
│   │   ├── index.astro            # Main landing page
│   │   ├── 404.astro              # Custom 404 error page
│   │   └── blog/
│   │       ├── index.astro        # Blog listing page (/blog)
│   │       └── [...slug].astro    # Individual post pages (/blog/<slug>)
├── public/
│   ├── favicon.svg                # Site favicon (coffee emoji)
│   ├── robots.txt                 # Search engine directives
│   └── blog/                      # Blog post images (per-post subdirectory)
├── astro.config.mjs               # Astro configuration with sitemap
├── package.json                   # Node dependencies
├── tsconfig.json                  # TypeScript configuration
├── Dockerfile                     # Multi-stage Docker build
├── docker-compose.yml             # Docker Compose setup
├── nginx.conf                     # Nginx configuration for production
├── .gitignore                     # Git ignore rules
└── README.md                      # User-facing documentation

Color Palette

The site uses CSS custom properties for theming. All colors are defined in src/layouts/BaseLayout.astro:

--color-bg: #1e1e2e           /* Dark background (Catppuccin Mocha base) */
--color-text: #cdd6f4          /* Light text */
--color-text-dim: #a6adc8      /* Dimmed text for less emphasis */
--color-accent: #cba6f7        /* Mauve accent */
--color-accent-bright: #f5c2e7 /* Pink accent for highlights */
--color-surface: #313244       /* Surface color for borders/cards */
--color-blue: #89b4fa          /* Blue for links */
--color-green: #a6e3a1         /* Green for code */
--color-peach: #fab387         /* Peach for labels */

Component Architecture

BaseLayout.astro

The base layout provides:

  • HTML structure and meta tags
  • Global CSS reset and typography
  • CSS custom properties for theming
  • Global animations (fadeIn)

index.astro

The main page includes these sections:

  1. Header - Title
  2. About - Introduction, age, status
  3. Cryptographic Keys - PGP fingerprint and SSH public key
  4. Games - Games Latte plays
  5. Socials - Links to social platforms
  6. Services - Self-hosted services
  7. Support - Crypto donation addresses
  8. Blog - Link to /blog
  9. Footer - Credits

blog/index.astro

Blog listing page at /blog. Fetches all non-draft posts from the blog content collection, sorted by date descending.

blog/[...slug].astro

Individual blog post page. Renders Markdown content using Astro's <Content /> component. Styles for prose content (headings, paragraphs, code blocks, images, etc.) are scoped within .content :global(...).

src/content/config.ts

Defines the blog content collection schema:

  • title (string) — post title
  • date (date) — publish date, used for sorting
  • description (string) — shown on the listing page
  • draft (boolean, optional) — set to true to hide from listing

404.astro

Custom error page with:

  • Themed styling matching the cozy aesthetic
  • Clear error message ("Lost in the Den?")
  • Action buttons to return home or visit Gitea
  • Responsive design for all devices

Development Workflow

Local Development

  1. Install dependencies:
npm install
  1. Start dev server (with hot reload):
npm run dev

Server runs at http://localhost:4321

  1. Build for production:
npm run build

Output goes to dist/ directory

  1. Preview production build:
npm run preview

Making Changes

Adding a new section:

  1. Edit src/pages/index.astro
  2. Add a new <section class="section new-section"> block
  3. Style it in the <style> tag at the bottom
  4. Use the .card class for consistent styling

Changing colors:

  1. Edit CSS custom properties in src/layouts/BaseLayout.astro
  2. All components will automatically update

Adding a service:

  1. Add a new .service-item div in the Services section
  2. Follow the existing structure with h3 link and description

Adding images:

  1. Place images in public/blog/<post-slug>/ directory
  2. Reference in Markdown with /blog/<post-slug>/image.jpg
  3. They'll be served as static assets by nginx

Adding a blog post:

  1. Create src/content/blog/my-post-slug.md
  2. Add frontmatter: title, date, description (and optionally draft: true)
  3. Write content in Markdown below the frontmatter
  4. The post appears automatically at /blog/my-post-slug

Docker Deployment

Building the Image

The Dockerfile uses a multi-stage build:

  • Stage 1: Node builder (builds Astro site)
  • Stage 2: Nginx server (serves static files)
docker build -t cozy-den .

Running Locally

docker run -d -p 3000:80 --name cozy-den cozy-den

Access at http://localhost:3000

Using Docker Compose

# Start
docker-compose up -d

# Stop
docker-compose down

# View logs
docker-compose logs -f

Deploying to Gitea Registry

# Tag for Gitea registry
docker tag cozy-den git.hiddenden.cafe/mats/cozy-den:latest

# Login to Gitea
docker login git.hiddenden.cafe

# Push
docker push git.hiddenden.cafe/mats/cozy-den:latest

Astro-Specific Information

File Extensions

  • .astro - Astro components (HTML-like syntax with embedded JS)
  • .mjs - ES module JavaScript files

Frontmatter

Code between --- at the top of .astro files runs at build time:

---
// This runs at build time (server-side)
const title = "My Page";
---
<h1>{title}</h1>

Styling

  • <style> tags in .astro files are scoped by default
  • Use <style is:global> for global styles
  • CSS is processed and optimized automatically

Static Generation

Astro generates static HTML at build time. No JavaScript runtime needed for this site (pure HTML/CSS output).

Common Tasks

Task: Add a new page

  1. Create src/pages/newpage.astro
  2. Import BaseLayout
  3. Add content
  4. Page will be available at /newpage

Example:

---
import BaseLayout from '../layouts/BaseLayout.astro';
---

<BaseLayout title="New Page">
  <div class="container">
    <h1>New Page</h1>
  </div>
</BaseLayout>

Task: Add a new section to homepage

  1. Open src/pages/index.astro
  2. Add new section before footer:
<section class="section my-section">
  <div class="container">
    <div class="card fade-in">
      <h2>My Section</h2>
      <p>Content here</p>
    </div>
  </div>
</section>
  1. Add styles in the <style> tag if needed

Task: Change the accent color

  1. Open src/layouts/BaseLayout.astro
  2. Modify --color-accent and --color-accent-bright
  3. Site updates automatically

Task: Add animation to new element

  1. Add fade-in class to element
  2. Or create new animation in BaseLayout.astro:
@keyframes slideIn {
  from { transform: translateX(-20px); opacity: 0; }
  to { transform: translateX(0); opacity: 1; }
}
.slide-in { animation: slideIn 0.6s ease-out; }

Troubleshooting

Build fails with TypeScript errors

  • Check tsconfig.json extends correct config
  • Ensure all props are properly typed in components

Styles not applying

  • Check if you need is:global on style tag
  • Verify CSS custom properties are defined in BaseLayout

Docker build fails

  • Ensure package.json and package-lock.json are present
  • Check Node version compatibility (needs 18+)

Changes not showing in dev

  • Hard refresh browser (Ctrl+Shift+R)
  • Restart dev server
  • Clear .astro cache directory

Future Enhancements

Ideas for future development:

  • Add blog section using Astro's content collections
  • Create custom 404 page
  • Add RSS feed for blog
  • Create reusable components for service items
  • Add more animations and transitions
  • Integrate with analytics (privacy-friendly, self-hosted)

Resources

Notes for AI Assistants

When working with this project:

  1. Maintain the cozy aesthetic (warm colors, soft animations)
  2. Keep the site lightweight and fast (static HTML/CSS)
  3. Follow the existing component structure
  4. Use CSS custom properties for theming
  5. Ensure responsive design for mobile
  6. Add appropriate TypeScript types when needed
  7. Test both dev and production builds
  8. Verify Docker build works after changes