077cc06d75
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.
335 lines
9.2 KiB
Markdown
335 lines
9.2 KiB
Markdown
# 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`:
|
|
|
|
```css
|
|
--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:
|
|
```bash
|
|
npm install
|
|
```
|
|
|
|
2. Start dev server (with hot reload):
|
|
```bash
|
|
npm run dev
|
|
```
|
|
Server runs at `http://localhost:4321`
|
|
|
|
3. Build for production:
|
|
```bash
|
|
npm run build
|
|
```
|
|
Output goes to `dist/` directory
|
|
|
|
4. Preview production build:
|
|
```bash
|
|
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)
|
|
|
|
```bash
|
|
docker build -t cozy-den .
|
|
```
|
|
|
|
### Running Locally
|
|
|
|
```bash
|
|
docker run -d -p 3000:80 --name cozy-den cozy-den
|
|
```
|
|
|
|
Access at `http://localhost:3000`
|
|
|
|
### Using Docker Compose
|
|
|
|
```bash
|
|
# Start
|
|
docker-compose up -d
|
|
|
|
# Stop
|
|
docker-compose down
|
|
|
|
# View logs
|
|
docker-compose logs -f
|
|
```
|
|
|
|
### Deploying to Gitea Registry
|
|
|
|
```bash
|
|
# 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:
|
|
```astro
|
|
---
|
|
// 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:
|
|
```astro
|
|
---
|
|
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:
|
|
```astro
|
|
<section class="section my-section">
|
|
<div class="container">
|
|
<div class="card fade-in">
|
|
<h2>My Section</h2>
|
|
<p>Content here</p>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
```
|
|
|
|
3. 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:
|
|
```css
|
|
@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:
|
|
- [x] Add blog section using Astro's content collections
|
|
- [x] 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
|
|
|
|
- [Astro Documentation](https://docs.astro.build)
|
|
- [Astro Components](https://docs.astro.build/en/core-concepts/astro-components/)
|
|
- [Astro Styling](https://docs.astro.build/en/guides/styling/)
|
|
- [Docker Documentation](https://docs.docker.com)
|
|
|
|
## 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
|