🟢 astro-pwa-starter
An opinionated Astro starter for building robust static websites.
✨ Feature Set
- ✅ Full PWA support out-of-the-box.
- ✅ Achieves a 100 SEO score out-of-the-box.
- ✅ Comes with TailwindCSS pre-installed.
- ✅ Full TypeScript support.
- ✅ Framework agnostic.
- ✅ Has sensible ESLint and Prettier configurations baked-in.
- ✅ Includes recommended SEO meta tags and favicons
- ✅ Straight-forward file structure, import aliases, and developer experience.
📦 Dependencies
Here is a list of core dependencies that astro-pwa-starter relies on in case you need to extend the starter/look into more documentation:
Package | Purpose |
---|---|
@astrojs/sitemap |
Generates an accessible sitemap for Astro websites. |
@astrojs/tailwind |
Automatically sets up TailwindCSS. |
astro-compress |
Compresses all static assets into minified files. |
astro-seo |
Provides a helpful component for configuring SEO. |
vite-plugin-pwa |
Configures a service-worker for offline-accessability and generates a webmanifest for PWA compliance. |
🤖 Commands
All commands are run from the root of the project, from a terminal:
Command | Action |
---|---|
pnpm install |
Installs dependencies |
pnpm run dev |
Starts local dev server at localhost:3000 |
pnpm run build |
Build your production site to ./dist/ |
pnpm run preview |
Preview your build locally, before deploying |
pnpm run astro ... |
Run CLI commands like astro add , astro preview |
pnpm run astro --help |
Get help using the Astro CLI |
👋 Getting Started Guide
Introduction and prerequisites
astro-pwa-starter is an opinionated Astro starter, meaning it ships with a pre-determined file structure and procedure for doing things. In this getting started guide we'll walk you through how to use the starter for your project.
Understanding the project structure
First, and foremost, is the project structure, in other words, how the files are laid out in the project. The starter follows a very similar convention to the one seen in Astro's own documentation. However, we've made some changes:
- Every static asset should be placed inside
/src/assets/
instead of the public folder, there are two subfolders (/img
and/svg
) to distinguish between images and graphics. - Use the
/utils
to include any helper scripts or configuration files like GraphQL clients or TypeScript types. - The
src/components/globals
folder contains three premade global components: the site header, footer, and layout (we'll talk about the layout in a bit).
Most of where you'll work is directly inside /src
. If you're curious to know what every file and directory in the starter does, checkout the documentation after reading this guide.
Creating pages
When you create a new page, place it inside the /src/pages/
directory and make sure it's a .astro
file. Then, import the <Layout />
component as such:
---
import { Layout } from "@globals"
---
<Layout title="Home Page"> // ... </Layout>
You'll notice we imported the component from @globals
, we'll talk about that later.
The <Layout />
global component is responsible for rendering your website's <header />
, <main />
, and <footer />
tags. Not only that, it also injects page-specific SEO such as a page title and description. Refer to the documentation on <Layout />
to see what props you can pass to it.
Make sure to always include a layout component on every page!
Creating components
Place new components inside the /src/components
directory.
We highly recommend for you to follow a directory-based approach when creating new components. That is, create a new directory inside of /src/components
such as /src/components/HelloWorld
, then place your component logic inside. The structure should look like this:
components
└── HelloWorld
├── HelloWorld.astro
└── index.ts
You'll notice we also threw in a index.ts
file. This is where you should export the component as a named export:
// index.ts
export { default as HelloWorld } from "./HelloWorld.astro"
Doing a directory-based approach and named export is good for two reasons:
- It compartamentalizes all component logic into discrete folders (including styles or extra scripts)
- It prevents you from accidently renaming a component later on in the project (named exports help with naming consistency).
When you want to use <HelloWorld />
, you can import it using our handy-dandy import aliases:
import { HelloWorld } from "@component/HelloWorld"
Again, we'll talk about import aliasing in more detail in a bit!
Working with images and SVGs
We mentioned it briefly before but there exists a /src/assets
directory where you're supposed to throw in your images and SVGs. This directoy actually has two subdirectories that look like this:
assets
img
svg
icons
It's straightforward but just to make it clear:
- Add all your .png, .jpeg, .avif, .webp, etc. into the
img
directory - Add all your SVGs into the
svg
directory orsvg/icons
directory depending on if it's an icon or regular graphic.
You can then reference your static assets using an import alias like so:
import MyAwesomeImage from "@img/my-awesome-image.png"
import SVGBackground from "@svg/svg-background.svg"
import SomeIcon from "@icon/some-icon.svg
Again we will talk about import aliases in more detail soon!
Configuring the default SEO
astro-pwa-starter ships with an SEO configuration file to setup defaults for your website!
You'll find it inside the /utils
folder (note, we put it there because it's a configuration file!). It's called seoConfig.ts
and it exports two very important objects:
- seoConfig
- manifest
seoConfig
is used in the <Layout />
component to set default SEO values. These include values like a site-wide description, site-wide thumbnail, etc. If you pass props to <Layout />
then those will overwrite the default SEO values.
manifest
is used to generate your website manifest file, which is important for PWA-compliance.
There are helpful comments within seoConfig.ts
that will guide you when configuring and customizing the file.
Make sure you fully customize every recommended field to take full advantage of astro-pwa-starter's built-in SEO optimization!
Don't forget to also customize the color themes present in <Layout />
and browserconfig.xml
!
If you want to learn more about seoConfig.ts
, checkout the documentation after finishing this guide.
Customizing SEO for a page
We briefly mentioned it before but the global <Layout />
component also handles your page's SEO. You can pass it different, SEO-based props like title
, description
, or image
to set the page's title, description, and OpenGraph Thumbnail:
---
import { Layout } from "@globals"
---
<Layout title="Home Page" description="Welcome to my website's homepage!">
// ...
</Layout>
If you're working with an error page like 404.astro
, then you can pass a disableIndexing
prop to completely remove the page from crawlers:
---
import { Layout } from "@globals"
---
<Layout title="Not Found" disableIndexing="{true}"></Layout>
Using a custom favicon
We recommend using a service like Favycon to generate your website's favicons (this is what we used). Make sure you have a 512x512 maskable icon before generating your favicons!
After generation, you can directly paste your favicons straight into /public/favicons
. Make sure to overwrite/replace all favicons in the directory. Afterwards, you'll be up and running with your own custom favicon.
syncore-astro-starter is already pre-configured to pull favicons from /public/favicons
, so as long as you used Favycon/have the exact same favicons we had originally then the starter will be able to automatically pull and inject your favicons in the final build.
Import aliases
Finally, import aliases.
One the best features of astro-pwa-starter is its extensive list of import aliases.
For those unfamiliar with import aliases, they make working with components and external assets much easier. Instead of having to directly reference an asset like such:
import { MyComponent } from "../../components/MyComponent"
import SomeImage from "../../assets/img/some-image.png"
You instead can do something more streamlined:
import { MyComponent } from "@component/MyComponent"
import SomeImage from "@img/some-image.png"
The best part about this is that you can use an import alias at any level in your website and still be able to access the asset you're trying to reach. No more ../../../../
hell.
For quick reference, here's a list of all import aliases available to you:
Alias | Purpose | Example |
---|---|---|
@globals |
Fetch global components | import { Layout } from "@globals |
@component/* |
Fetch regular components | import { PriceTable } from "@component/PriceTable |
@util/* |
Import utilities | import { seoConfig, manifest } from "@util/seoConfig" |
@img/* |
Imports images | import MyImage from "@img/my-image.png" |
@svg/* |
Imports SVGs | import MySVG from "@svg/my-svg.svg |
@icon/* |
Imports SVG icons from /svg/icons |
import MyIcon from "@icon/my-icon.svg |
@style/* |
Fetches stylesheets | import "@style/tailwind.css" |
📖 Documentation
This documentation looks at astro-pwa-starter from a top-down perspective, providing insight into every directory and file available in the base starter.
File structure
The base project structure looks like this:
.vscode
public
├── favicons
├── browserconfig.xml
├── humans.txt
└── robots.txt
src
├── assets
│ ├── img
│ └── svg
│ └── icons
├── components
│ └── global
│ ├── Footer
│ │ ├── Footer.astro
│ │ └── index.ts
│ ├── Header
│ │ ├── Header.astro
│ │ └── index.ts
│ └── Layout
│ ├── index.ts
│ └── Layout.astro
├── pages
│ └── index.astro
├── styles
│ └── tailwind.css
└── env.d.ts
utils
└── seoConfig.ts
.editorconfig
.env
.eslintrc.js
.gitignore
.npmrc
.prettierignore
.prettierrc.js
astro.config.ts
package.json
README.md
tailwind.config.js
tsconfig.json
/.vscode
This directory contains VSCode-related configurations and recommended extensions.
/public
This directory contains all public website assets. Astro will not parse any of these files and will serve them as is.
/favicons
Website favicons.
browserconfig.xml
Defines how OSs should use and theme the website's favicon.
You should only modify the <TileColor />
tag to match with the website's primary color.
humans.txt
Defines people/organizations who worked on the website. Refer to humans.txt for more information.
robots.txt
Defines how browser crawlers should index the website.
You do not need to modify this file.
/src
Contains all pages and components the website utilizes. This is where most of the coding-action takes place.
Every file within src will be transformed according to Astro and Vite's build tools.
/assets
Assets contains all images, svgs, and icons used in the website. It is placed inside the src
folder so that Vite transformations can be made to assets.
/img
Contains all images for use on the website. You should not place .svg files in this directory.
Images are accessible to the website via the @img/*
import alias. You can import images like this:
---
import BackgroundImage from "@img/background-image.png"
---
<img src="{BackgroundImage}" alt="A sunny blue sky" />
/svg
Contains all SVGs the website uses. You should not place .jpg | .png | .webp or other image-based files into this directory.
SVGs can be imported using the @svg/*
import alias. You can import SVGs like this:
---
import WavyPatterns from "@svg/wavy-patterns.svg"
---
<img src="{WavyPatterns}" alt="" />
/icons
Contains all icons that the website will use. Only .svg files should go in here.
You can import icons using the @svg/icons/* import alias.
/components/
Defines site-wide components. Every component should be placed inside a directory that has the same name as the exported component.
Components can be imported using the @component/*
import alias. For example:
---
import {CustomComponent} from "@component/CustomComponent"
---
<CustomComponent />
/global
Contains components that are considered to be global across the website.
You most likely will not need to add components here.
Footer.astro
Defines the footer for the website. This component does not take any props.
Header.astro
Defines the header for the website. This component does not take any props.
Layout.astro
Defines the global layout for the website. This component will wrap every single page in the website and append the <Header/>
and <Footer/>
components where necessary. It will also manage SEO for the website.
Refer to the following as an example of how to set SEO:
---
import {Layout} from "@utils"
---
<Layout title="Page title" description="This is the page description">
// ...
</Layout>
Props
Name | Type | Required? | Description | |
---|---|---|---|---|
title | String | Yes | Title of the page. | |
ogTitle | String | No | OpenGraph title for the page (can be longer than title) | |
description | String | No | Description of the page. If not set then the default description is used. | |
image | {url: string, alt: string} | No | Image thumbnail for the page. If not set then the default image is used. | |
disableIndexing | Boolean | No | Whether or not to disable indexing. |
/pages
Contains all pages for the website.
Astro uses file-based routing, meaning that all .astro files inside of the pages directory will directly convert into paths on the final website.
For example, /pages/test.astro will be accessible on the final website at /test.
All pages should use the Layout component. You should also define SEO for each page through the Layout component. Refer back to the <Layout />
component to see how to add SEO.
/styles
Contains .css
files.
tailwind.css
Defines the default configuration for TailwindCSS as well as any custom CSS needed for the website.
env.d.ts
Defines custom typings for the environment. This is used in conjunction with .env
to add type support for any environment variables.
Refer to Astro's docs on typed environment variables for more information.
/utils
Defines external utilities for the website. These can be third-party scripts that require additional setup and configuration, packages such as graphql-request
or firebase
, or configuration files written in TypeScript.
All utilities can be imported into the website using the @util/*
import alias, example:
---
// ...
import { seoConfig } from "@util/seoConfig"
---
// seoConfig is now a useable object
seoConfig.ts
Defines the default SEO configuration for the website. This exports a large object with props that come from astro-seo. It also defines the manifest configuration for the site's PWA integration
The default configuration is:
// Type imports
import type { ManifestOptions } from "vite-plugin-pwa"
/**
* Defines the default SEO configuration for the website.
*/
export const seoConfig = {
baseURL: "https://example.com", // Change this to your production URL.
description:
"Astro PWA Starter is an opionated Astro starter for building robust static websites.", // Change this to be your website's description.
type: "website",
image: {
url: "https://picsum.photos/1200/630", // Change this to your website's thumbnail.
alt: "OpenGraph thumbnail description.", // Change this to your website's thumbnail description.
width: 1200,
height: 630
},
siteName: "Astro PWA Starter", // Change this to your website's name,
twitter: {
card: "summary_large_image"
}
}
/**
* Defines the configuration for PWA webmanifest.
*/
export const manifest: Partial<ManifestOptions> = {
name: "Astro PWA Starter",
short_name: "Astro PWA Starter",
description:
"Astro PWA Starter is an opionated Astro starter for building robust static websites.",
theme_color: "#30E130",
background_color: "#ffffff",
display: "minimal-ui",
icons: [
{
src: "/favicons/favicon-192x192.png",
sizes: "192x192",
type: "image/png"
},
{
src: "/favicons/favicon-512x512.png",
sizes: "512x512",
type: "image/png"
},
{
src: "/favicons/favicon-512x512.png",
sizes: "512x512",
type: "image/png",
purpose: "any maskable"
}
]
}
.editorconfig
Defines configurations for code indentation and end-of-line styling.
This file should not be modified so as to keep a consistent code environment across IDEs.
You don't need to modify this file.
.env
Contains environment variables.
Vite will inject these variables into the website at runtime.
Any public-facing environment variable should be prefixed with PUBLIC_
.
.eslintrc.js
Defines linting rules for Astro, Svelte, and TypeScript files.
You don't need to modify this file (unless you want to extend the ESLint configuration).
.gitignore
Ignores files and directors from git version control.
You don't need to modify this file (unless you need to ignore additional files).
.npmrc
Specific configuration to allow pnpm to resolve Astro dependencies.
This file should not be modified.
.prettierignore
Ignores files from Prettier linting.
This file should not be modified.
.prettierrc.js
Defines a Prettier configuration for formatting Astro, Svelte, and TypeScript files.
This file should not be modified (unless you want to extend any Prettier rules).
astro.config.ts
Defines the configuration used by Astro. Follow documentation for the config file over at Astro's documentation website
package.json
Defines all Node packages.
README.md
README file for the starter.
tailwind.config.ts
Configuration file for TailwindCSS.
tsconfig.json
Defines configurations for TypeScript.
This file should not be modified.