- β HTML5 semantics
- β Images optimized at build time by πautomatio
- β
<picture>element respose
Despite this repo being public, it doesn't mean that all these assets are open-source and/or copyright free, or even that you may use any of them.
Please, ask for permission first, by contacting us: info@junglestar.org
All photos Β© Binocle. All rights reserved. Thanks, Junglestar team.
my-astro-site/
βββ src/
β βββ pages/ # Routes - each .astro = a page
β β βββ index.astro # Homepage (/)
β β βββ about.astro # About page (/about)
β βββ layouts/ # Reusable page layouts
β β βββ Layout.astro
β βββ components/ # Reusable components
β β βββ Card.astro
β βββ styles/ # CSS files (processed by Vite)
β β βββ global.css
β βββ scripts/ # JS files (processed & optimized by Vite!)
β βββ main.js
βββ public/ # Static assets (served as-is, NO processing)
β βββ favicon.ico
β βββ legacy-libs/ # Old libraries that shouldn't be processed
β βββ jquery.min.js
βββ .zed/ # Zed editor settings
β βββ settings.json
βββ astro.config.mjs # Config file (NOT .ts!)
βββ package.json
βββ pnpm-lock.yaml # PNPM lock file
βββ biome.json # Biome config (formats JS/CSS)
import { defineConfig } from 'astro/config';
export default defineConfig({
// Keep it simple - no config needed for basic sites
});{
"$schema": "https://biomejs.dev/schemas/1.9.4/schema.json",
"files": {
"include": ["src/**/*.js", "src/**/*.css", "*.mjs"],
"ignore": ["dist", "node_modules", ".astro"]
},
"formatter": {
"enabled": true,
"indentStyle": "space",
"indentWidth": 2,
"lineWidth": 100
},
"linter": {
"enabled": true,
"rules": {
"recommended": true
}
},
"javascript": {
"formatter": {
"quoteStyle": "single",
"semicolons": "asNeeded"
}
},
"overrides": [
{
"include": ["*.astro"],
"formatter": {
"enabled": false
},
"linter": {
"enabled": false
}
}
]
}{
"format_on_save": "on",
"formatter": {
"language_server": {
"name": "biome"
}
},
"lsp": {
"biome": {
"settings": {
"require_config_file": true
}
}
}
}---
// JavaScript here - NOT TypeScript!
const { title } = Astro.props;
---
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>{title}</title>
<link rel="stylesheet" href="/src/styles/global.css">
</head>
<body>
<slot /> <!-- Page content goes here -->
<!-- <script src="/scripts/main.js"></script> -->
</body>
</html>---
// JavaScript in the frontmatter
import Layout from '../layouts/Layout.astro';
import Card from '../components/Card.astro';
const pageTitle = "Home";
const items = ['First', 'Second', 'Third'];
---
<Layout title={pageTitle}>
<h1>Welcome</h1>
<!-- Use JavaScript expressions -->
<ul>
{items.map(item => <li>{item}</li>)}
</ul>
<!-- Use components -->
<Card title="Hello" />
<!-- Inline scripts if needed -->
<script>
console.log('This runs on the client');
</script>
</Layout>---
// Component JavaScript
const { title, href = "#" } = Astro.props;
---
<div class="card">
<h3>{title}</h3>
<a href={href}>Learn more β</a>
</div>
<style>
/* Scoped CSS - only affects THIS component */
.card {
border: 1px solid #ddd;
padding: 1rem;
border-radius: 8px;
}
</style>/* Regular CSS file */
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: system-ui, sans-serif;
line-height: 1.6;
}// JavaScript in src/ gets processed & optimized by Vite!
// You can use ES modules, imports, etc.
import { utils } from './utils.js';
document.addEventListener('DOMContentLoaded', () => {
console.log('Site loaded!');
utils.init();
});---
// JavaScript goes here (runs at build time)
const data = "Hello";
---
<!-- HTML template -->
<div>{data}</div>
<style>
/* Scoped CSS */
</style>
<script>
// Client-side JavaScript
</script>---
// Import from src/ for processing
import '../scripts/main.js';
import '../styles/global.css';
---
<!-- For scripts in src/ (processed by Vite) -->
<script src="../scripts/main.js"></script>
<!-- For scripts in public/ (NO processing, needs is:inline) -->
<script is:inline src="/unprocessed-legacy.js"></script>public/
βββ images/logo.png β /images/logo.png
βββ fonts/custom.woff2 β /fonts/custom.woff2
βββ libs/jquery.forget.it β /libs/jquery.rip.js (already expired)
src/= Vite processes & optimizes your JS/CSSpublic/= Served as-is, no processing at all
---
// src/pages/blog/[slug].astro
export function getStaticPaths() {
return [
{ params: { slug: 'post-1' } },
{ params: { slug: 'post-2' } },
];
}
const { slug } = Astro.params;
---
<h1>Post: {slug}</h1>Migration from Jekyll/Static Site
# Create new Astro project
pnpm create astro@latest my-site -- --template minimal --no-install --no-git
# Go to project
cd my-site
# Install dependencies
pnpm install
# Install Biome (faster, no Prettier needed)
pnpm add -D @biomejs/biome
pnpm biome init
# Start dev server
pnpm dev- Copy your static files to
public/ - Convert HTML files to
.astrofiles insrc/pages/ - Extract common HTML to
src/layouts/Layout.astro - Keep using your existing JS/CSS - just import them!
{
"scripts": {
"dev": "astro dev",
"build": "astro build",
"preview": "astro preview",
"format": "biome format --write ./src",
"lint": "biome lint ./src"
}
}<!-- index.html -->
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="style.css">
</head>
<body>
<h1>My Site</h1>
<script src="script.js"></script>
</body>
</html>---
// src/pages/index.astro
---
<html>
<head>
<link rel="stylesheet" href="/style.css">
</head>
<body>
<h1>My Site</h1>
<script src="/script.js"></script>
</body>
</html>Well, from > 0.2.x It's TS, Old JS has been refactored with TS!