Build landing page using Island Architecture
Mostafa Milly
Posted on March 10, 2023
Island architecture
is a software architecture pattern that involves creating small, isolated, and self-contained modules, or "islands," that can communicate with each other through well-defined interfaces. Each island is designed to perform a specific function or set of related functions, and can be developed and maintained independently of the other islands. This makes it easier to build complex systems that are flexible, scalable, and maintainable over time.
What is Astro
Astro is a static site generator that is designed to help developers build modern, performant websites using a component-based architecture. It uses a combination of HTML, CSS, and JavaScript to generate static pages that can be hosted on a server or served from a content delivery network (CDN).
To use Astro with the island architecture pattern, you can break your website or web application into a set of islands, with each island representing a distinct feature or set of features. You can then use Astro to generate static pages for each island, along with the necessary JavaScript and CSS files, and deploy them to a CDN or server.
Getting started
In this tutorial, you will learn how to create simple Astro page which contains multiple islands.
The target of this tutorial to build a simple landing page using Reactjs,Solidjs,Svelete and Vuejs.
Step 1: Set up the project
First, create a new Astro project using the following command:
npm create astro@latest
For React Integration you can use the following command:
npx Astro add react
For Solidjs integration you can use the following command:
npx Astro add solid
For Vuejs integration you can use the following command:
npx Astro add vue
Last for Svelete integration you can use the following command:
npx Astro add svelte
Step 2: building layout component in Svelte
- First create file under
src/layouts
and name it asLayout.svelte
layouts/Layout.svelte
<div class="container">
<slot />
</div>
<style>
.container {
margin: 0 auto;
padding: 0;
display: flex;
flex-direction: column;
row-gap: 10px;
width: 100%;
}
</style>
In this component we create wrapper component for all our components.
By using <slot />
I can inject the children's components into the Layout Svelete component (It's kind of children prop inside Reactjs)
After creating the layout component, we can import it into our index.astro page under pages folder:
pages/index.astro
---
import Layout from "../layouts/Layout.svelte";
---
<Layout client:load>
</Layout>
-
client:load
directive enables to load and hydrate our layout component immediately as soon as possible.
You can learn more about client directives in this link
Step 3: Create a header component using Vuejs
- First create file under
src/components
and name it asHeader.vue
components/Header.vue
<template>
<header>
<h1>{{ title }}</h1>
<nav>
<ul>
<li><a href="#">Home</a></li>
<li><a href="#">About</a></li>
<li><a href="#">Contact</a></li>
</ul>
</nav>
</header>
</template>
<script>
export default {
name: "Header",
props: {
title: {
type: String,
required: true,
},
},
};
</script>
<style>
header {
display: flex;
justify-content: space-between;
align-items: center;
padding: 1rem;
background-color: #fff;
color: #262525;
}
h1 {
margin: 0;
font-size: 2rem;
}
nav ul {
list-style: none;
display: flex;
}
nav li {
margin-right: 1rem;
}
nav a {
color: #262525;
text-decoration: none;
font-weight: bold;
}
</style>
After that we can import our Header
Vuejs component into our Astro page:
pages/index.astro
---
import Layout from "../layouts/Layout.svelte";
import Header from "../components/Header.vue";
---
<Layout client:load>
<Header title="Astro Islands" client:visible />
</Layout>
As you can see, I can pass props to vue Header component.
client:visible is also client directive to load the component only if its visible on the user viewport
Step 4: Create hero section using Solidjs
- First create file under
src/components
and name it asHero.tsx
components/Hero.tsx
import { createSignal } from "solid-js";
function Hero() {
const [isLoggedIn, setIsLoggedIn] = createSignal(false);
function handleLogin() {
setIsLoggedIn(true);
}
return (
<div class="hero" style="padding: 3rem;">
<div
class="hero-content"
style="background-color: #fff; padding: 2rem; border-radius: 8px; box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2); margin-top: -4rem; z-index: 1;"
>
<div style="display : flex; column-gap:20px; margin-top : 8px">
<img
src="./hero.svg"
alt="Hero image"
style="max-width: 200px; height: auto; border-radius: 8px;"
/>
<div>
<h1 style="font-size: 3rem; margin-bottom: 1rem;">
Welcome to our website
</h1>
<p style="font-size: 1.5rem; margin-bottom: 2rem;">
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
</p>
{!isLoggedIn() && (
<button
onClick={handleLogin}
style="background-color: #007bff; color: #fff; padding: 1rem 2rem; border: none; border-radius: 4px; font-size: 1.2rem; cursor: pointer;"
>
Login
</button>
)}
</div>
</div>
</div>
</div>
);
}
export default Hero;
After that we can import our Hero
Solidjs component into our Astro page:
pages/index.astro
---
import Layout from "../layouts/Layout.svelte";
import Header from "../components/Header.vue";
import Hero from "../components/Hero.tsx";
---
<Layout client:load>
<Header title="Astro Islands" client: visible />
<Hero client:visible />
</Layout>
Step 5: Create contact us form using Reactjs
- First create file under
src/components
and name it asContactForm.tsx
components/ContactForm.tsx
import React, { useState } from "react";
import "./ContactForm.css";
type ContactFormProps = {
onSubmit?: (name: string, email: string, message: string) => void;
};
const ContactForm: React.FC<ContactFormProps> = ({ onSubmit }) => {
const [name, setName] = useState("");
const [email, setEmail] = useState("");
const [message, setMessage] = useState("");
const handleSubmit = (e: React.FormEvent<HTMLFormElement>) => {
e.preventDefault();
onSubmit?.(name, email, message);
};
return (
<form className="contact-form" onSubmit={handleSubmit}>
<div className="contact-form__field">
<label className="contact-form__label">Name:</label>
<input
type="text"
id="name"
value={name}
onChange={(e) => setName(e.currentTarget.value)}
required
className="contact-form__input"
/>
</div>
<div className="contact-form__field">
<label className="contact-form__label">Email:</label>
<input
type="email"
id="email"
value={email}
onChange={(e) => setEmail(e.currentTarget.value)}
required
className="contact-form__input"
/>
</div>
<div className="contact-form__field">
<label className="contact-form__label">Message:</label>
<textarea
id="message"
value={message}
onChange={(e) => setMessage(e.currentTarget.value)}
required
className="contact-form__textarea"
></textarea>
</div>
<button type="submit" className="contact-form__submit">
Submit
</button>
</form>
);
};
export default ContactForm;
After that we can import our ContactForm
Reactjs component into our Astro page:
---
import Layout from "../layouts/Layout.svelte";
import Header from "../components/Header.vue";
import Hero from "../components/Hero.tsx";
import ContactForm from "../components/ContactForm.tsx";
---
<Layout client:load>
<Header title="Astro Islands" client:visible />
<Hero client:visible />
<ContactForm client:visible />
</Layout>
Step 6: Create footer component using Svelte
Last thing we want to create a footer component using Svelte so we will create our footer component file:
components/Footer.svelte
<footer class="footer">
<nav class="footer__nav">
<a href="#" class="footer__link">Home</a>
<a href="#" class="footer__link">About</a>
<a href="#" class="footer__link">Contact</a>
</nav>
<p class="footer__text">© 2023 Astro Islands. All rights reserved.</p>
</footer>
<style>
.footer {
background-color: #f8f8f8;
padding: 20px;
display: flex;
flex-direction: column;
align-items: center;
}
.footer__nav {
display: flex;
gap: 20px;
margin-bottom: 10px;
}
.footer__link {
color: #333;
text-decoration: none;
font-weight: bold;
font-size: 1.2rem;
transition: color 0.2s ease-in-out;
}
.footer__link: hover {
color: #007bff;
}
.footer__text {
font-size: 0.9rem;
color: #333;
margin-top: 10px;
}
</style>
Last thing we should modify our Astro page to include our Svelte Footer:
---
import Layout from "../layouts/Layout.svelte";
import Header from "../components/Header.vue";
import Hero from "../components/Hero.tsx";
import ContactForm from "../components/ContactForm.tsx";
import Footer from "../components/Footer.svelte";
---
<Layout client: load>
<Header title="Astro Islands" client:visible />
<Hero client:visible />
<ContactForm client:visible />
<Footer client:visible />
</Layout>
In this way you create simple landing page using Reactjs, Vuejs , Solidjs and Svelte.
This is repository link: Link
Thank you for reading, and see you soon with another post ❤️
Posted on March 10, 2023
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.