What is Astro?
Astro is the web framework designed for a content-rich website, with minimum JavaScript sent to the client. By default, zero JavaScript is sent.
- Server-first approach (Not SPA, but MPA) for SEO and fast speed
- Easy to use like HTML for any developers
- For dynamic UI, you can use any framework such as React, Vue, Svelte, etc.
If you're thinking of making a website that only requires a minimum amount of JavaScript such as a Landing Page, Blog or Company page, Astro would be the best option!
I used Astro to make a landing page this time.
Let's get started
Installation
- Install astro
npm create astro@latest {directory name}
While you're installing, answer the questions like this.
- Install React
npx astro add react
- Install Tailwindcss
npx astro add tailwind
Tailwind Css Setup
Delete unnecessary code in Layout.astro and index.astro.
- Font
Add google font inside <head>
in Layout.astro file.
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Roboto:wght@300;400;500;700&display=swap" rel="stylesheet">
Change tailwind.condig.mjs file
/** @type {import('tailwindcss').Config} */
module.exports = {
content: ['./src/**/*.{astro,html,js,jsx,md,mdx,svelte,ts,tsx,vue}'],
theme: {
extend: {
fontFamily: {
body: ['"Roboto", sans-serif'],
},
},
},
plugins: [],
};
- Theme
Add to tailwind config for theme colours, fontSize or anything you want.
/** @type {import('tailwindcss').Config} */
module.exports = {
content: ['./src/**/*.{astro,html,js,jsx,md,mdx,svelte,ts,tsx,vue}'],
theme: {
extend: {
fontFamily: {
body: ['"Roboto", sans-serif'],
},
// Any theme you want to add here
colors: {
black: '#000000',
white: '#FFFFFF',
brand: '#4FD1C5',
main: {
50: '#F1FAFA',
100: '#E3F5F4',
200: '#B9E7E3',
300: '#8FD9D1',
400: '#4B9D96',
500: '#37928A',
600: '#2C756E',
700: '#276661',
800: '#215853',
900: '#1C4945',
},
}
},
},
plugins: [],
};
Now we've done the minimum settings and are ready to make a website!
How to use it
After you finish setting, you see the default directory like this.
So we can follow this directory structure.
In this case, I made a landing page with only one page, so the page file looks like this.
---
import Layout from '../layouts/Layout.astro';
import Hero from '../components/Hero.astro';
import Problem from '../components/Problem.astro';
import Solution from '../components/Solution.astro';
import Feature from '../components/Feature.astro';
import Comparison from '../components/Comparison.astro';
import Flow from '../components/Flow.astro';
import Faq from '../components/Faq.astro';
import Message from '../components/Message.astro';
import Cta from '../components/Cta.astro';
import Footer from '../components/Footer.astro';
---
<Layout>
<main class='pt-[58px] lg:pt-[72px]'>
<Hero />
<Problem />
<Solution />
<Feature />
<Comparison />
<Flow />
<Faq />
<Message />
<Cta />
<Footer />
</main>
</Layout>
Component Script & Props
Let's make components.
Astro components are made up of two separate parts.
---
// Component Script (JavaScript)
---
<!-- Component Template (HTML + JS Expressions) -->
In the Component Script using a code fence (---), you can import other files, define variables or fetch API.
In the Component Template, you can use JavaScript expressions similar to JSX.
---
const points = [
{ text: 'No intermediary fees at all!' },
{ text: 'Unlimited scouts' },
{ text: 'Only ¥50,000 per month (completely free until the end of March 2023)'
---
<ul class="flex flex-col gap-2.5 relative z-20 lg:flex-row lg:gap-14">
{points.map((point) => (
<li>{point.text}</li>
))}
</ul>;
You can also pass props through components like React.
---
type Props = {
title: string;
body: string;
href: string;
}
const { href, title, body } = Astro.props;
---
<li class="link-card">
<a href={href}>
<h2>
{title}
<span>→</span>
</h2>
<p>
{body}
</p>
</a>
</li>
---
import Card from './Card.astro';
---
<Card title="Astro is awesome" body="This is..." href="https://www.google.com" />
Use with React
You can make dynamic UI parts like Accordion with React.
import { useState } from "react";
import { ChevronDown, ChevronUp } from "./icons";
type AccordionProps = {
title: string;
description: string;
};
export const Accordion = ({ title, description }: AccordionProps) => {
const [isOpen, setIsOpen] = useState(false);
return (
<div className="bg-white px-4 md:px-8 rounded-md">
<button
className="py-3 flex items-center text-sm text-left w-full md:py-4 md:text-md"
onClick={() => setIsOpen((prev) => !prev)}
>
<span className="text-main-800 font-bold pr-2 text-xl shrink-0 leading-none self-start md:text-2xl md:pr-4">
Q
</span>
{title}
<span className="h-6 w-6 flex-shrink-0 pl-2 md:h-7 md:w-7 ml-auto">
{isOpen ? <ChevronUp /> : <ChevronDown />}
</span>
</button>
<div
className={`flex flex-start font-normal text-sm border-t border-gray-200 text-left md:text-md overflow-hidden transition-all ${
isOpen ? "h-auto py-4 md:py-5" : "h-0 py-0"
}`}
>
<span className="text-main-400 font-bold pr-2 text-xl shrink-0 leading-none md:text-2xl md:pr-4">
A
</span>
<p>{description}</p>
</div>
</div>
);
};
Then you import it in astro component.
---
import { Accordion } from './Accordion';
const faqs = [
{
title:
'Question1',
description:
'Answer1',
},
{
title:
'Question2',
description:
'Answer2',
},
];
---
<section id='faq' class='bg-gray-100'>
<div class='section-container'>
<div class='font-bold text-center'>
<h2 class='text-2xl md:text-4xl'>FAQ</h2>
<div class='flex flex-col gap-4 mt-8'>
{
faqs.map((faq) => (
<Accordion
title={faq.title}
description={faq.description}
client:visible
/>
))
}
</div>
</div>
</div>
</section>
The cool part is you can pass props the same as React from Astro file😳
You can use JS frameworks like this because of Astro Island.
Astro Island is dynamic UI components on the page. Astro can combine static HTML and interactive UI components in one page.
With interactive islands, you need to mark using client:* directives to control how the UI components are hydrated. I used client:visible
to display the Accordion component. It means that priority is low, and this component is rendered when it is in the viewport because the accordion is not necessary to render in the first view.
You can refer to all the directives from here: Client Directives
Image
You can use the image optimization feature provided by Astro.
However, it is a bit different from when I used it last year, so I won't explain it in detail.
The official website says the image will be optimized if you do the following.
- Images are kept in src/ directory
- Images must be imported into the file
- Use Astro’s built-in component
---
import { Image } from 'astro:assets';
import localBirdImage from '../../images/subfolder/localBirdImage.png';
---
<Image src={localBirdImage} alt="A bird sitting on a nest of eggs."/>
Astro Icon
For icons, astro-icon is definitely helpful.
Super easy. You store svg file in /src/icons/
and use astro-icon.
npx astro add astro-icon
---
import { Icon } from 'astro-icon/components'
---
<!-- Embed the contents of the `/src/icons/logo.svg` file -->
<Icon name="logo" />
<!-- Embed the contents of the `/src/icons/logos/astro.svg` file -->
<Icon name="logos/astro" />
You can also use open source icon set.
npm install @iconify-json/mdi
---
import { Icon } from 'astro-icon/components'
---
<!-- Embed the `account` icon from `@iconify-json/mdi` -->
<Icon name="mdi:account" />
Conclusion
Astro not only offers a seamless user experience but also intuitively understands the needs of web developers. It is truly an amazing framework for creating websites!
Top comments (0)