Refactor code and restructure directories
In response to the changes made to the directory structure of the project, the code has been refactored to adjust image import paths across various sections. It also involves reorganizing components into appropriate folders based on their roles in the application. Along with this, a new utility file for navigation links has been introduced, and configurations for authorizing remote images have been added to Astro configuration file, suggesting an enhancement in SEO performance.
This commit is contained in:
parent
a7c3dee7a2
commit
addbb5457a
31 changed files with 618 additions and 225 deletions
459
README.md
459
README.md
|
@ -1,47 +1,444 @@
|
||||||
# Astro Starter Kit: Minimal
|
# ScrewFast: Landing Page/Blog Template
|
||||||
|
|
||||||
```sh
|

|
||||||
npm create astro@latest -- --template minimal
|
|
||||||
|
ScrewFast is a landing and blog template crafted with simplicity and ease of use in mind. Designed for small to medium-sized projects, ScrewFast provides a seamless setup experience for developers and content creators alike. It combines the power of [Astro](https://astro.build/), [Tailwind CSS](https://tailwindcss.com/), and [Preline UI](https://preline.co/) to deliver a less complex, yet functional and visually appealing web presence.
|
||||||
|
|
||||||
|
## Why Choose ScrewFast?
|
||||||
|
|
||||||
|
- **Simplified Architecture:** Whether you're building a portfolio, a company landing page, or a simple blog, ScrewFast's architecture is straightforward and easy to navigate, helping you get your project off the ground quickly.
|
||||||
|
- **Tailored for Smaller Projects:** With a focus on performance and minimal overhead, ScrewFast is ideal for projects that require a clean and professional online presence without the complexity of larger-scale solutions.
|
||||||
|
- **Customizable and Extensible:** While the core structure of the template prioritizes simplicity, it doesn't compromise on customizability. Tap into the potential of Astro's component-based architecture and Tailwind's utility-first styling to expand the template as needed.
|
||||||
|
|
||||||
|
## Features
|
||||||
|
|
||||||
|
- **Astro Framework:** A web framework for building content-driven websites efficiently.
|
||||||
|
- **Tailwind CSS:** A utility-first CSS framework for rapid UI development.
|
||||||
|
- **Preline UI:** A set of accessible and reusable components that are both attractive and functional.
|
||||||
|
- **GSAP Integration:** Smooth, professional-grade animations to captivate your audience.
|
||||||
|
- **Markdown Content Collections:** Manage your product and blog content effortlessly with markdown.
|
||||||
|
- **SEO-Friendly:** Pages structured for optimal search engine performance.
|
||||||
|
- **Responsive Design:** Fully responsive layout to ensure your site looks great on all devices.
|
||||||
|
|
||||||
|
## Getting Started
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary>
|
||||||
|
This guide will help you set up the Astro project on your local machine and introduce you to some essential commands for development and deployment.
|
||||||
|
</summary>
|
||||||
|
<br>
|
||||||
|
|
||||||
|
### Installation
|
||||||
|
|
||||||
|
To begin, you'll need to install all the dependencies required for the project. Open your terminal, navigate to the project's root directory, and run the following command:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm install
|
||||||
```
|
```
|
||||||
|
|
||||||
[](https://stackblitz.com/github/withastro/astro/tree/latest/examples/minimal)
|
This command will install all the dependencies listed in the project's `package.json` file.
|
||||||
[](https://codesandbox.io/p/sandbox/github/withastro/astro/tree/latest/examples/minimal)
|
|
||||||
[](https://codespaces.new/withastro/astro?devcontainer_path=.devcontainer/minimal/devcontainer.json)
|
|
||||||
|
|
||||||
> 🧑🚀 **Seasoned astronaut?** Delete this file. Have fun!
|
### Common Commands
|
||||||
|
|
||||||
## 🚀 Project Structure
|
Once the installation is completed, you can use various npm scripts defined in `package.json` to manage the development lifecycle of your project:
|
||||||
|
|
||||||
Inside of your Astro project, you'll see the following folders and files:
|
```bash
|
||||||
|
# Starts the local development server
|
||||||
|
|
||||||
```text
|
npm run dev
|
||||||
/
|
|
||||||
├── public/
|
# Builds your production site and outputs it to ./dist/
|
||||||
├── src/
|
|
||||||
│ └── pages/
|
npm run build
|
||||||
│ └── index.astro
|
|
||||||
└── package.json
|
# Previews your built site locally before deploying it
|
||||||
|
|
||||||
|
npm run preview
|
||||||
|
|
||||||
|
# Runs Astro CLI commands such as astro add or astro check
|
||||||
|
|
||||||
|
npm run astro
|
||||||
|
|
||||||
|
# Displays help information for Astro CLI commands
|
||||||
|
|
||||||
|
npm run astro --help
|
||||||
```
|
```
|
||||||
|
|
||||||
Astro looks for `.astro` or `.md` files in the `src/pages/` directory. Each page is exposed as a route based on its file name.
|
### Learning More
|
||||||
|
|
||||||
There's nothing special about `src/components/`, but that's where we like to put any Astro/React/Vue/Svelte/Preact components.
|
To learn more about the available Astro CLI commands and further understand the capabilities of Astro, refer to [Astro's documentation](https://docs.astro.build/).
|
||||||
|
</details>
|
||||||
|
|
||||||
Any static assets, like images, can be placed in the `public/` directory.
|
## Project Structure
|
||||||
|
|
||||||
## 🧞 Commands
|
<details>
|
||||||
|
<summary>
|
||||||
|
ScrewFast is organized into modular components, content, and layout systems, making development and content management a breeze. Here's a quick overview of the project's directory structure:
|
||||||
|
</summary>
|
||||||
|
<br>
|
||||||
|
|
||||||
All commands are run from the root of the project, from a terminal:
|
```md
|
||||||
|
|
||||||
| Command | Action |
|
src/
|
||||||
| :------------------------ | :----------------------------------------------- |
|
├── components/ # Reusable components
|
||||||
| `npm install` | Installs dependencies |
|
│ ├── Meta.astro # Meta component for SEO
|
||||||
| `npm run dev` | Starts local dev server at `localhost:4321` |
|
│ ├── sections/ # Sectional components for various parts of the website
|
||||||
| `npm run build` | Build your production site to `./dist/` |
|
│ ├── ThemeIcon.astro # Theme switcher icon component
|
||||||
| `npm run preview` | Preview your build locally, before deploying |
|
│ └── ui/ # UI components categorized by their functionality
|
||||||
| `npm run astro ...` | Run CLI commands like `astro add`, `astro check` |
|
├── content/ # Content files in markdown for blog posts, insights, and products
|
||||||
| `npm run astro -- --help` | Get help using the Astro CLI |
|
│ ├── blog/ # Blog posts written in markdown
|
||||||
|
│ ├── insights/ # Insights articles
|
||||||
|
│ ├── products/ # Product details
|
||||||
|
│ └── config.ts # Site configuration
|
||||||
|
├── images/ # Image assets for the website
|
||||||
|
├── layouts/ # Layout components
|
||||||
|
│ └── MainLayout.astro # Main layout component
|
||||||
|
├── pages/ # Astro pages representing each website section or view
|
||||||
|
│ ├── 404.astro # Custom 404 page
|
||||||
|
│ ├── blog/ # Blog listing and post pages
|
||||||
|
│ ├── contact.astro # Contact page
|
||||||
|
│ ├── index.astro # Home page
|
||||||
|
│ ├── insights/ # Insights listing and detail pages
|
||||||
|
│ ├── products/ # Product listing and detail pages
|
||||||
|
│ ├── robots.txt.ts # Dynamic generation of robots.txt
|
||||||
|
│ └── services.astro # Services offered
|
||||||
|
└── utils/ # Utility functions
|
||||||
|
|
||||||
## 👀 Want to learn more?
|
```
|
||||||
|
|
||||||
Feel free to check [our documentation](https://docs.astro.build) or jump into our [Discord server](https://astro.build/chat).
|
</details>
|
||||||
|
|
||||||
|
## Static Assets and Public Resources
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary>
|
||||||
|
The `public` directory contains all the static files that your project can serve directly to the browser. Here's a breakdown of the contents within the `public` folder:
|
||||||
|
</summary>
|
||||||
|
<br>
|
||||||
|
- Favicons and device icons (e.g., `favicon.ico`, `apple-touch-icon.png`)
|
||||||
|
- PWA (Progressive Web App) manifest and icons for improved mobile support (e.g., `manifest.webmanifest`, `icon-512.png`)
|
||||||
|
- `social.png`: An image for social media sharing previews
|
||||||
|
- `scripts`: Third-party libraries and scripts
|
||||||
|
- `gsap`: GreenSock Animation Platform files for creating high-performance animations
|
||||||
|
- `lenis`: Smooth scrolling library for improved scroll interactions
|
||||||
|
- `preline`: Set of UI component scripts from Preline UI
|
||||||
|
|
||||||
|
Here's the layout of the `public` directory:
|
||||||
|
|
||||||
|
```md
|
||||||
|
|
||||||
|
public/
|
||||||
|
├── apple-touch-icon.png
|
||||||
|
├── favicon.ico
|
||||||
|
├── icon-192.png
|
||||||
|
├── icon-512.png
|
||||||
|
├── icon.svg
|
||||||
|
├── manifest.webmanifest
|
||||||
|
├── maskable_icon.png
|
||||||
|
├── maskable_icon_x512.png
|
||||||
|
├── scripts/
|
||||||
|
│ └── vendor/
|
||||||
|
│ ├── gsap/
|
||||||
|
│ │ └── gsap.min.js
|
||||||
|
│ ├── lenis/
|
||||||
|
│ │ └── lenis.js
|
||||||
|
│ └── preline/
|
||||||
|
│ ├── accordion/
|
||||||
|
│ ├── collapse/
|
||||||
|
│ ├── overlay/
|
||||||
|
│ └── tabs/
|
||||||
|
└── social.png
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
When adding or updating icons and favicons, ensure that they match the sizes expected by various devices and that they're referenced correctly in the head of your HTML document.
|
||||||
|
|
||||||
|
The scripts in the `public/scripts/vendor` directory are essential for the interactivity and aesthetic features of the website. Do not remove these unless you plan to replace their functionality.
|
||||||
|
</details>
|
||||||
|
|
||||||
|
## Integrations and Enhancements
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary>
|
||||||
|
ScrewFast leverages the power of Astro and associated integrations to deliver exceptional site performance and a seamless user experience. Here are some notable integrations and enhancements included in the project:
|
||||||
|
</summary>
|
||||||
|
<br>
|
||||||
|
|
||||||
|
### Lenis for Smooth Scrolling
|
||||||
|
|
||||||
|
Experience buttery smooth scrolling with [Lenis](https://lenis.studiofreight.com/). We've integrated Lenis to provide an enhanced scrolling experience that's both fluid and responsive.
|
||||||
|
|
||||||
|
Here's how we set up Lenis in `src/layouts/MainLayout.astro`:
|
||||||
|
|
||||||
|
```html
|
||||||
|
<script is:inline src="/scripts/vendor/lenis/lenis.js"></script>
|
||||||
|
<script is:inline>
|
||||||
|
// Script to handle Lenis library settings for smooth scrolling
|
||||||
|
const lenis = new Lenis({
|
||||||
|
smooth: true,
|
||||||
|
smoothTouch: false
|
||||||
|
});
|
||||||
|
|
||||||
|
function raf(time) {
|
||||||
|
lenis.raf(time); // Update Lenis on each animation frame
|
||||||
|
requestAnimationFrame(raf); // Continuously invoke the raf function at refresh rate
|
||||||
|
}
|
||||||
|
requestAnimationFrame(raf); // Start the loop
|
||||||
|
</script>
|
||||||
|
<style>
|
||||||
|
html.lenis {
|
||||||
|
height: auto;
|
||||||
|
}
|
||||||
|
.lenis.lenis-smooth {
|
||||||
|
scroll-behavior: auto !important;
|
||||||
|
}
|
||||||
|
.lenis.lenis-smooth [data-lenis-prevent] {
|
||||||
|
overscroll-behavior: contain;
|
||||||
|
}
|
||||||
|
.lenis.lenis-stopped {
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
.lenis.lenis-scrolling iframe {
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
```
|
||||||
|
|
||||||
|
Please note that smooth scrolling can affect accessibility and performance on some devices, so be sure to test it comprehensively across different environments.
|
||||||
|
|
||||||
|
If you would like to remove Lenis, just comment out or delete these lines, and the scrolling will return to the default behavior.
|
||||||
|
|
||||||
|
### GSAP Integration
|
||||||
|
|
||||||
|
For individual product pages, [GSAP](https://gsap.com/) has been integrated to add engaging animations that execute as soon as the product page loads. You can find and modify the GSAP configuration in the script sections of the product page file located at `src/pages/products/[...slug].astro`:
|
||||||
|
|
||||||
|
```html
|
||||||
|
<script is:inline src="/scripts/vendor/gsap/gsap.min.js"></script>
|
||||||
|
<script>
|
||||||
|
window.addEventListener("load", (event) => {
|
||||||
|
if (window.gsap) {
|
||||||
|
const gsap = window.gsap;
|
||||||
|
// Initialize GSAP animations...
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
```
|
||||||
|
|
||||||
|
**Customizing Animations:**
|
||||||
|
|
||||||
|
Please tailor the GSAP animations within this script to fit your project's look and feel. The provided example is a starting point, representing how to leverage GSAP for immediate visual impact as a product page loads.
|
||||||
|
|
||||||
|
**Modifying or Removing Animations:**
|
||||||
|
|
||||||
|
This integration is designed for flexibility:
|
||||||
|
|
||||||
|
- To adjust an animation, modify the properties and parameters within the `gsap.from` method or add new GSAP calls as needed.
|
||||||
|
- If GSAP is not required or you wish to rely on a different methodology, remove the the relevant code.
|
||||||
|
|
||||||
|
We've chosen to keep the integration lean and focused, but GSAP's comprehensive documentation can be referred to for more intricate animation work: [GSAP Documentation](https://gsap.com/docs/v3/).
|
||||||
|
|
||||||
|
### Hiding Scrollbar
|
||||||
|
|
||||||
|
To achieve a cleaner and more spacious design, the default scrollbar has been visually removed. While this choice fits the aesthetic goals of the project, it's important to consider that hiding scrollbars can sometimes affect accessibility and user experience. We recommend evaluating this design decision within the context of your user base and their needs.
|
||||||
|
|
||||||
|
For those who prefer custom-styled scrollbars, we suggest using the [tailwind-scrollbar](https://adoxography.github.io/tailwind-scrollbar/) plugin, which adds Tailwind CSS utilities for scrollbar styles, allowing for more controlled customization that can also meet accessibility standards.
|
||||||
|
|
||||||
|
If you wish to return the default scrollbar, you can comment out or remove the following CSS from `src/layouts/MainLayout.astro`:
|
||||||
|
|
||||||
|
```html
|
||||||
|
<style>
|
||||||
|
.scrollbar-hide::-webkit-scrollbar {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
.scrollbar-hide {
|
||||||
|
-ms-overflow-style: none;
|
||||||
|
scrollbar-width: none;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
```
|
||||||
|
|
||||||
|
Additionally, update the `<html>` tag to remove the `scrollbar-hide` class, resulting in:
|
||||||
|
|
||||||
|
```html
|
||||||
|
<html lang="en" class="scroll-pt-16">
|
||||||
|
```
|
||||||
|
|
||||||
|
### SEO Configuration
|
||||||
|
|
||||||
|
The ScrewFast template includes a flexible SEO configuration that allows you to optimize each page for search engines and social media platforms effectively. By utilizing the `Meta.astro` component, you can easily customize important metadata such as page titles, descriptions, author information, and social media images.
|
||||||
|
|
||||||
|
The `Meta.astro` component is designed with default properties. However, you have the option to override these defaults by passing custom props. Furthermore, you can extend the metadata by adding additional properties as needed.
|
||||||
|
|
||||||
|
#### Customizing Metadata with Meta.astro
|
||||||
|
|
||||||
|
The `Meta.astro` component comes preset with default metadata, but you can override these defaults per page:
|
||||||
|
|
||||||
|
```astro
|
||||||
|
// Extract props with our default values
|
||||||
|
const { meta = "ScrewFast offers top-tier hardware tools and expert construction services.", structuredData } = Astro.props;
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Applying Metadata in Layouts
|
||||||
|
|
||||||
|
In your `MainLayout.astro` (or other layout files), you'd set up the props that you want to pass to the `Meta` component:
|
||||||
|
|
||||||
|
```astro
|
||||||
|
---
|
||||||
|
const { meta, structuredData } = Astro.props;
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
meta?: string;
|
||||||
|
structuredData?: object;
|
||||||
|
}
|
||||||
|
---
|
||||||
|
|
||||||
|
<Meta meta={meta} structuredData={structuredData} />
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Customizing Metadata on Individual Pages
|
||||||
|
|
||||||
|
Finally, for each page, you can pass custom metadata through the layout:
|
||||||
|
|
||||||
|
```astro
|
||||||
|
---
|
||||||
|
import MainLayout from '../layouts/MainLayout.astro';
|
||||||
|
---
|
||||||
|
|
||||||
|
<MainLayout meta="Find the perfect hardware tools with ScrewFast for all your construction needs.">
|
||||||
|
<!-- Page content -->
|
||||||
|
</MainLayout>
|
||||||
|
```
|
||||||
|
|
||||||
|
With this setup, the Meta component receives the custom meta description and applies it to the page's metadata. If no custom value is passed, the default from `Meta.astro` will be used instead.
|
||||||
|
|
||||||
|
#### Extending Metadata for SEO
|
||||||
|
|
||||||
|
For a more robust SEO strategy, you can create additional properties in the `Meta.astro` component. For instance, you may want to include specific Open Graph tags for article publishing dates or tags for Twitter-specific metadata.
|
||||||
|
|
||||||
|
#### Structured Data and Rich Snippets
|
||||||
|
|
||||||
|
The `Meta.astro` component also handles structured data using JSON-LD format, enhancing how search engines interpret the content of your pages. This can improve how your content appears in search results with rich snippets. You can configure the structured data by modifying the `structuredData` property with relevant schema.org types and properties.
|
||||||
|
|
||||||
|
#### Using Astro SEO Integrations
|
||||||
|
|
||||||
|
While the template provides a custom SEO solution, you may choose to utilize an Astro integration such as [Astro SEO](https://github.com/jonasmerlin/astro-seo#readme) for additional SEO features and optimizations. Integrating such a package might provide more automated metadata management or additional SEO-focused functionality.
|
||||||
|
|
||||||
|
### Robots.txt
|
||||||
|
|
||||||
|
`robots.txt` is dynamically generated using the code found in src/pages/robots.txt.ts. This configuration follows the example from the Astro Docs:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
import type { APIRoute } from 'astro';
|
||||||
|
|
||||||
|
const robotsTxt = `
|
||||||
|
User-agent: *
|
||||||
|
Allow: /
|
||||||
|
|
||||||
|
Sitemap: ${new URL('sitemap-index.xml', import.meta.env.SITE).href}
|
||||||
|
`.trim();
|
||||||
|
|
||||||
|
export const GET: APIRoute = () => {
|
||||||
|
return new Response(robotsTxt, {
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'text/plain; charset=utf-8',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
### Astro Integrations
|
||||||
|
|
||||||
|
Maximize your website's efficiency with these built-in Astro integrations:
|
||||||
|
|
||||||
|
- [Astro Compressor](https://github.com/sondr3/astro-compressor#readme): Automatically compresses your Astro-generated site using gzip or brotli, ensuring faster load times for your users.
|
||||||
|
Configure the compressor in your `astro.config.mjs` file:
|
||||||
|
|
||||||
|
```mjs
|
||||||
|
export default defineConfig({
|
||||||
|
// ...other Astro configurations
|
||||||
|
integrations: [...other Astro integrations, compressor({ gzip: false, brotli: true })],
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
- [Astro Sitemap](https://docs.astro.build/en/guides/integrations-guide/sitemap/): Automatically generates a sitemap for your website, which is vital for SEO and helping search engine bots crawl your pages effectively. Add the sitemap configuration to your astro.config.mjs, specifying your site's base URL and any additional options:
|
||||||
|
|
||||||
|
```mjs
|
||||||
|
export default defineConfig({
|
||||||
|
// ...
|
||||||
|
site: 'https://example.com',
|
||||||
|
integrations: [sitemap()],
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
### Flexibility with Integrations
|
||||||
|
|
||||||
|
The great thing about Astro is its rich ecosystem of integrations, allowing you to tailor project functionalities to your exact needs. Feel free to explore [Astro integrations page](https://astro.build/integrations/) and add additional capabilities as you see fit.
|
||||||
|
</details>
|
||||||
|
|
||||||
|
## Tools and Technologies
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary>
|
||||||
|
This project is built using a variety of tools and technologies that enhance its performance, maintainability, and developer experience. Below is a list of the key tools and their roles in the project:
|
||||||
|
</summary>
|
||||||
|
<br>
|
||||||
|
|
||||||
|
### Preline UI
|
||||||
|
|
||||||
|
Interactive components such as navbars, modals, and accordions are based on Preline UI, a popular open-source component library.
|
||||||
|
|
||||||
|
### Tailwind CSS
|
||||||
|
|
||||||
|
Our project's styling is completely powered by Tailwind CSS's utility-first classes. This approach provides us with the flexibility to design custom layouts and components directly in our markup.
|
||||||
|
|
||||||
|
In our project configuration, we use `prettier-plugin-tailwindcss` in `.prettierrc` to ensure consistent styling:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"plugins": ["prettier-plugin-tailwindcss"]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Deployment and Security
|
||||||
|
|
||||||
|
The project is deployed on `Vercel`, leveraging the platform's capabilities for seamless CI/CD. Security headers and caching behavior are configured in `vercel.json` to ensure best practices in security and performance:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"headers": [
|
||||||
|
{
|
||||||
|
"source": "/(.*)",
|
||||||
|
"headers": [
|
||||||
|
{
|
||||||
|
"key": "Content-Security-Policy",
|
||||||
|
"value": "default-src 'self'; [other-directives]"
|
||||||
|
}
|
||||||
|
// Additional security headers...
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### HTML Minification
|
||||||
|
|
||||||
|
To further enhance the site's performance, we use `process-html.mjs`, a [custom script](https://straffesites.com/en/blog/optimize-astro-html-post-build) that minifies HTML files after the build process.
|
||||||
|
|
||||||
|
```mjs
|
||||||
|
// Post-build HTML minification script snippet
|
||||||
|
// ...
|
||||||
|
await Promise.all(
|
||||||
|
files.map(async (file) => {
|
||||||
|
// Processing and minification logic here
|
||||||
|
})
|
||||||
|
);
|
||||||
|
```
|
||||||
|
|
||||||
|
Please refer to the respective documentations for each tool:
|
||||||
|
|
||||||
|
- [Preline UI Documentation](https://preline.co/docs)
|
||||||
|
- [Tailwind CSS Documentation](https://tailwindcss.com/docs)
|
||||||
|
- [Vercel Documentation](https://vercel.com/docs)
|
||||||
|
- [html-minifier Documentation](https://github.com/kangax/html-minifier)
|
||||||
|
|
||||||
|
</details>
|
||||||
|
|
|
@ -2,11 +2,14 @@ import { defineConfig } from 'astro/config';
|
||||||
import tailwind from "@astrojs/tailwind";
|
import tailwind from "@astrojs/tailwind";
|
||||||
import vercelStatic from '@astrojs/vercel/static';
|
import vercelStatic from '@astrojs/vercel/static';
|
||||||
import sitemap from "@astrojs/sitemap";
|
import sitemap from "@astrojs/sitemap";
|
||||||
|
|
||||||
import compressor from "astro-compressor";
|
import compressor from "astro-compressor";
|
||||||
|
|
||||||
// https://astro.build/config
|
// https://astro.build/config
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
|
// https://docs.astro.build/en/guides/images/#authorizing-remote-images
|
||||||
|
image: {
|
||||||
|
domains: ["images.unsplash.com"],
|
||||||
|
},
|
||||||
site: 'https://screwfast.uk',
|
site: 'https://screwfast.uk',
|
||||||
integrations: [tailwind(), sitemap(), compressor({ gzip: false, brotli: true })],
|
integrations: [tailwind(), sitemap(), compressor({ gzip: false, brotli: true })],
|
||||||
output: 'static',
|
output: 'static',
|
||||||
|
|
|
@ -4,7 +4,6 @@
|
||||||
// 'meta' sets a default description meta tag to describe the page content.
|
// 'meta' sets a default description meta tag to describe the page content.
|
||||||
// 'structuredData' defines default structured data in JSON-LD format to enhance search engine understanding of the page (for SEO purposes).
|
// 'structuredData' defines default structured data in JSON-LD format to enhance search engine understanding of the page (for SEO purposes).
|
||||||
const defaultProps = {
|
const defaultProps = {
|
||||||
title: "ScrewFast", // Default title
|
|
||||||
meta: "ScrewFast offers top-tier hardware tools and expert construction services to meet all your project needs. Start exploring and contact our sales team for superior quality and reliability.",
|
meta: "ScrewFast offers top-tier hardware tools and expert construction services to meet all your project needs. Start exploring and contact our sales team for superior quality and reliability.",
|
||||||
structuredData: {
|
structuredData: {
|
||||||
"@context": "https://schema.org",
|
"@context": "https://schema.org",
|
||||||
|
@ -18,9 +17,10 @@ const defaultProps = {
|
||||||
// Extract props with default values assigned from defaultProps. Values can be overridden when the component is used.
|
// Extract props with default values assigned from defaultProps. Values can be overridden when the component is used.
|
||||||
// For example:
|
// For example:
|
||||||
// <MainLayout title="Custom Title" meta="Custom description." />
|
// <MainLayout title="Custom Title" meta="Custom description." />
|
||||||
const { title = defaultProps.title, meta = defaultProps.meta, structuredData = defaultProps.structuredData } = Astro.props;
|
const { meta = defaultProps.meta, structuredData = defaultProps.structuredData } = Astro.props;
|
||||||
|
|
||||||
// Define the metadata for your website and individual pages
|
// Define the metadata for your website and individual pages
|
||||||
|
const title: string = "ScrewFast"; // Set default title
|
||||||
const ogTitle: string = "ScrewFast: Hardware Tools & Construction Services"; // Set the Open Graph title
|
const ogTitle: string = "ScrewFast: Hardware Tools & Construction Services"; // Set the Open Graph title
|
||||||
const author: string = "Emil Gulamov"; // Set the author's name
|
const author: string = "Emil Gulamov"; // Set the author's name
|
||||||
const ogDescription: string =
|
const ogDescription: string =
|
||||||
|
|
|
@ -11,9 +11,7 @@ import TextAreaInput from "../ui/forms/input/TextAreaInput.astro";
|
||||||
const title: string = "Contact us";
|
const title: string = "Contact us";
|
||||||
const subTitle: string =
|
const subTitle: string =
|
||||||
"Have questions or want to discuss a project? Reach out, and let's craft the perfect solution with our tools and services.";
|
"Have questions or want to discuss a project? Reach out, and let's craft the perfect solution with our tools and services.";
|
||||||
|
|
||||||
const formTitle: string = "Fill in the form below";
|
const formTitle: string = "Fill in the form below";
|
||||||
|
|
||||||
const formSubTitle: string = "We'll get back to you in 1-2 business days.";
|
const formSubTitle: string = "We'll get back to you in 1-2 business days.";
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
|
@ -2,57 +2,14 @@
|
||||||
// Import the necessary dependencies
|
// Import the necessary dependencies
|
||||||
import FooterSocialLink from "../ui/links/FooterSocialLink.astro";
|
import FooterSocialLink from "../ui/links/FooterSocialLink.astro";
|
||||||
import EmailFooterInput from "../ui/forms/input/EmailFooterInput.astro";
|
import EmailFooterInput from "../ui/forms/input/EmailFooterInput.astro";
|
||||||
|
import { footerLinks, socialLinks } from "../../utils/navigation.ts";
|
||||||
|
|
||||||
// Footer Section Names
|
// Footer Section Names
|
||||||
const sectionOne: string = "Product";
|
|
||||||
const sectionTwo: string = "Company";
|
|
||||||
const sectionThree: string = "Stay up to date";
|
const sectionThree: string = "Stay up to date";
|
||||||
|
|
||||||
// Define the variables that will be used in this component
|
// Define the variables that will be used in this component
|
||||||
const content: string =
|
const content: string =
|
||||||
"Stay updated with the latest tools and exclusive deals.";
|
"Stay updated with the latest tools and exclusive deals.";
|
||||||
|
|
||||||
/* TypeScript type for links. */
|
|
||||||
type Links = {
|
|
||||||
title: string;
|
|
||||||
url: string;
|
|
||||||
};
|
|
||||||
|
|
||||||
// An array of links for Product section
|
|
||||||
const product: Links[] = [
|
|
||||||
{
|
|
||||||
title: "Tools & Equipment",
|
|
||||||
url: "#",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: "Construction Services",
|
|
||||||
url: "/services",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: "Pricing",
|
|
||||||
url: "#",
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
// An array of links for Company section
|
|
||||||
const company: Links[] = [
|
|
||||||
{
|
|
||||||
title: "About us",
|
|
||||||
url: "#",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: "Blog",
|
|
||||||
url: "/blog",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: "Careers",
|
|
||||||
url: "#",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: "Customers",
|
|
||||||
url: "#",
|
|
||||||
},
|
|
||||||
];
|
|
||||||
---
|
---
|
||||||
|
|
||||||
<footer class="w-full bg-neutral-300 dark:bg-neutral-900">
|
<footer class="w-full bg-neutral-300 dark:bg-neutral-900">
|
||||||
|
@ -116,53 +73,33 @@ const company: Links[] = [
|
||||||
></path>
|
></path>
|
||||||
</svg>
|
</svg>
|
||||||
</div>
|
</div>
|
||||||
|
<!-- An array of links for Product and Company sections -->
|
||||||
<div class="col-span-1">
|
{
|
||||||
<h3 class="font-bold text-neutral-800 dark:text-neutral-200">
|
footerLinks.map((section) => (
|
||||||
{sectionOne}
|
<div class="col-span-1">
|
||||||
</h3>
|
<h3 class="font-bold text-neutral-800 dark:text-neutral-200">
|
||||||
|
{section.section}
|
||||||
<div class="mt-3 grid space-y-3">
|
</h3>
|
||||||
{
|
<ul class="mt-3 grid space-y-3">
|
||||||
product.map((item) => (
|
{section.links.map((link, index) => (
|
||||||
<p>
|
<li>
|
||||||
<a
|
<a
|
||||||
class="inline-flex gap-x-2 rounded-lg text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-300 dark:focus:outline-none dark:focus:ring-1"
|
href={link.url}
|
||||||
href={item.url}
|
class="inline-flex gap-x-2 rounded-lg text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-300 dark:focus:outline-none dark:focus:ring-1"
|
||||||
>
|
>
|
||||||
{item.title}
|
{link.name}
|
||||||
</a>
|
</a>
|
||||||
</p>
|
{section.section === "Company" && index === 2 ? (
|
||||||
))
|
<span class="ms-1 inline rounded-lg bg-[#e14d0b] px-2 py-1 text-xs font-bold text-neutral-50">
|
||||||
}
|
We're hiring!
|
||||||
</div>
|
</span>
|
||||||
</div>
|
) : null}
|
||||||
|
</li>
|
||||||
<div class="col-span-1">
|
))}
|
||||||
<h3 class="font-bold text-neutral-800 dark:text-neutral-200">
|
</ul>
|
||||||
{sectionTwo}
|
</div>
|
||||||
</h3>
|
))
|
||||||
|
}
|
||||||
<div class="mt-3 grid space-y-3">
|
|
||||||
{
|
|
||||||
company.map((item, index) => (
|
|
||||||
<p>
|
|
||||||
<a
|
|
||||||
class="inline-flex gap-x-2 rounded-lg text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-300 dark:focus:outline-none dark:focus:ring-1"
|
|
||||||
href={item.url}
|
|
||||||
>
|
|
||||||
{item.title}
|
|
||||||
</a>
|
|
||||||
{index === 2 ? (
|
|
||||||
<span class="ms-1 inline rounded-lg bg-[#e14d0b] px-2 py-1 text-xs text-neutral-50">
|
|
||||||
We're hiring
|
|
||||||
</span>
|
|
||||||
) : null}
|
|
||||||
</p>
|
|
||||||
))
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="col-span-2">
|
<div class="col-span-2">
|
||||||
<h3 class="font-bold text-neutral-800 dark:text-neutral-200">
|
<h3 class="font-bold text-neutral-800 dark:text-neutral-200">
|
||||||
|
@ -195,7 +132,7 @@ const company: Links[] = [
|
||||||
|
|
||||||
<!-- Social Brands -->
|
<!-- Social Brands -->
|
||||||
<div>
|
<div>
|
||||||
<FooterSocialLink url="#"
|
<FooterSocialLink url={socialLinks.facebook}
|
||||||
><svg
|
><svg
|
||||||
class="h-4 w-4 flex-shrink-0 fill-current text-neutral-700 dark:text-neutral-400"
|
class="h-4 w-4 flex-shrink-0 fill-current text-neutral-700 dark:text-neutral-400"
|
||||||
fill="currentColor"
|
fill="currentColor"
|
||||||
|
@ -207,7 +144,7 @@ const company: Links[] = [
|
||||||
>
|
>
|
||||||
</FooterSocialLink>
|
</FooterSocialLink>
|
||||||
|
|
||||||
<FooterSocialLink url="#"
|
<FooterSocialLink url={socialLinks.x}
|
||||||
><svg
|
><svg
|
||||||
class="h-4 w-4 flex-shrink-0 fill-current text-neutral-700 dark:text-neutral-400"
|
class="h-4 w-4 flex-shrink-0 fill-current text-neutral-700 dark:text-neutral-400"
|
||||||
fill="currentColor"
|
fill="currentColor"
|
||||||
|
@ -219,7 +156,7 @@ const company: Links[] = [
|
||||||
></FooterSocialLink
|
></FooterSocialLink
|
||||||
>
|
>
|
||||||
|
|
||||||
<FooterSocialLink url="https://github.com/mearashadowfax/ScrewFast"
|
<FooterSocialLink url={socialLinks.github}
|
||||||
><svg
|
><svg
|
||||||
class="h-4 w-4 flex-shrink-0 fill-current text-neutral-700 dark:text-neutral-400"
|
class="h-4 w-4 flex-shrink-0 fill-current text-neutral-700 dark:text-neutral-400"
|
||||||
fill="currentColor"
|
fill="currentColor"
|
||||||
|
@ -231,7 +168,7 @@ const company: Links[] = [
|
||||||
>
|
>
|
||||||
</FooterSocialLink>
|
</FooterSocialLink>
|
||||||
|
|
||||||
<FooterSocialLink url="#"
|
<FooterSocialLink url={socialLinks.google}
|
||||||
><svg
|
><svg
|
||||||
class="h-4 w-4 flex-shrink-0 fill-current text-neutral-700 dark:text-neutral-400"
|
class="h-4 w-4 flex-shrink-0 fill-current text-neutral-700 dark:text-neutral-400"
|
||||||
fill="currentColor"
|
fill="currentColor"
|
||||||
|
@ -243,7 +180,7 @@ const company: Links[] = [
|
||||||
>
|
>
|
||||||
</FooterSocialLink>
|
</FooterSocialLink>
|
||||||
|
|
||||||
<FooterSocialLink url="#"
|
<FooterSocialLink url={socialLinks.slack}
|
||||||
><svg
|
><svg
|
||||||
class="h-4 w-4 flex-shrink-0 fill-current text-neutral-700 dark:text-neutral-400"
|
class="h-4 w-4 flex-shrink-0 fill-current text-neutral-700 dark:text-neutral-400"
|
||||||
fill="currentColor"
|
fill="currentColor"
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
import ThemeIcon from "../ThemeIcon.astro";
|
import ThemeIcon from "../ThemeIcon.astro";
|
||||||
import NavLink from "../ui/links/NavLink.astro";
|
import NavLink from "../ui/links/NavLink.astro";
|
||||||
import Authentication from "./Authentication.astro";
|
import Authentication from "./Authentication.astro";
|
||||||
|
import { navBarLinks } from "../../utils/navigation.ts";
|
||||||
---
|
---
|
||||||
|
|
||||||
<!-- Main header component -->
|
<!-- Main header component -->
|
||||||
|
@ -130,11 +131,9 @@ import Authentication from "./Authentication.astro";
|
||||||
class="mt-5 flex flex-col gap-x-0 gap-y-4 md:mt-0 md:flex-row md:items-center md:justify-end md:gap-x-7 md:gap-y-0 md:ps-7"
|
class="mt-5 flex flex-col gap-x-0 gap-y-4 md:mt-0 md:flex-row md:items-center md:justify-end md:gap-x-7 md:gap-y-0 md:ps-7"
|
||||||
>
|
>
|
||||||
<!-- Navigation links and Authentication component -->
|
<!-- Navigation links and Authentication component -->
|
||||||
<NavLink url="/" name="Home" />
|
{navBarLinks.map(link => (
|
||||||
<NavLink url="/products" name="Products" />
|
<NavLink url={link.url} name={link.name} /></a>
|
||||||
<NavLink url="/services" name="Services" />
|
))}
|
||||||
<NavLink url="/blog" name="Blog" />
|
|
||||||
<NavLink url="/contact" name="Contact" />
|
|
||||||
|
|
||||||
<Authentication />
|
<Authentication />
|
||||||
<!-- ThemeIcon component specifically for larger screens -->
|
<!-- ThemeIcon component specifically for larger screens -->
|
||||||
|
|
|
@ -21,6 +21,7 @@ const subTitle: string =
|
||||||
class="h-full w-full object-cover object-center"
|
class="h-full w-full object-cover object-center"
|
||||||
draggable={"false"}
|
draggable={"false"}
|
||||||
format={"avif"}
|
format={"avif"}
|
||||||
|
loading={"eager"}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,8 +1,12 @@
|
||||||
---
|
---
|
||||||
// Define the variables that will be used in this component
|
// Define props from Astro
|
||||||
const title: string = "Trusted by Industry Leaders";
|
const { title, subTitle } = Astro.props;
|
||||||
const subTitle: string =
|
|
||||||
"Experience the reliability chosen by industry giants.";
|
// Define TypeScript interface for props
|
||||||
|
interface Props {
|
||||||
|
title: string;
|
||||||
|
subTitle: string;
|
||||||
|
}
|
||||||
---
|
---
|
||||||
|
|
||||||
<section
|
<section
|
|
@ -8,18 +8,33 @@ import Avatar from "../ui/avatars/Avatar.astro";
|
||||||
import FullStar from "../ui/stars/FullStar.astro";
|
import FullStar from "../ui/stars/FullStar.astro";
|
||||||
import HalfStar from "../ui/stars/HalfStar.astro";
|
import HalfStar from "../ui/stars/HalfStar.astro";
|
||||||
|
|
||||||
// Define the variables that will be used in this component
|
// Define props from Astro
|
||||||
const title: string = `Equip Your Projects with <span
|
const {
|
||||||
class="text-yellow-500 dark:text-yellow-400">ScrewFast</span>`;
|
title,
|
||||||
const subTitle: string =
|
subTitle,
|
||||||
"Top-quality hardware tools and expert construction services for every project need.";
|
primaryBtn,
|
||||||
const primaryBtn: string = "Start Exploring";
|
primaryBtnURL,
|
||||||
const primaryBtnURL: string = "/products";
|
secondaryBtn,
|
||||||
const secondaryBtn: string = "Contact Sales Team";
|
secondaryBtnURL,
|
||||||
const secondaryBtnURL: string = "/contact";
|
withReview,
|
||||||
const rating: number = 4.8;
|
starCount = 0,
|
||||||
const starCount: number = 4;
|
rating,
|
||||||
const reviews: string = "12.8k";
|
reviews,
|
||||||
|
} = Astro.props;
|
||||||
|
|
||||||
|
// Define TypeScript interface for props
|
||||||
|
interface Props {
|
||||||
|
title: string;
|
||||||
|
subTitle?: string;
|
||||||
|
primaryBtn?: string;
|
||||||
|
primaryBtnURL?: string;
|
||||||
|
secondaryBtn?: string;
|
||||||
|
secondaryBtnURL?: string;
|
||||||
|
withReview?: boolean;
|
||||||
|
starCount?: number;
|
||||||
|
rating?: string;
|
||||||
|
reviews?: string;
|
||||||
|
}
|
||||||
---
|
---
|
||||||
|
|
||||||
<!-- Defining a grid container that holds all the content -->
|
<!-- Defining a grid container that holds all the content -->
|
||||||
|
@ -48,6 +63,7 @@ const reviews: string = "12.8k";
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Review Section: This section presents avatars, review ratings and the number of reviews -->
|
<!-- Review Section: This section presents avatars, review ratings and the number of reviews -->
|
||||||
|
{ withReview ? (
|
||||||
<div class="mt-6 lg:mt-10">
|
<div class="mt-6 lg:mt-10">
|
||||||
<div class="py-5">
|
<div class="py-5">
|
||||||
<div class="text-center sm:flex sm:items-center sm:text-start">
|
<div class="text-center sm:flex sm:items-center sm:text-start">
|
||||||
|
@ -56,27 +72,26 @@ const reviews: string = "12.8k";
|
||||||
<div class="flex justify-center -space-x-3">
|
<div class="flex justify-center -space-x-3">
|
||||||
<Avatar
|
<Avatar
|
||||||
src="https://images.unsplash.com/photo-1568602471122-7832951cc4c5?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=facearea&facepad=2&w=300&h=300&q=80"
|
src="https://images.unsplash.com/photo-1568602471122-7832951cc4c5?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=facearea&facepad=2&w=300&h=300&q=80"
|
||||||
alt="Image Description"
|
alt="Avatar Description"
|
||||||
/>
|
/>
|
||||||
<Avatar
|
<Avatar
|
||||||
src="https://images.unsplash.com/photo-1531927557220-a9e23c1e4794?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=facearea&facepad=2&w=300&h=300&q=80"
|
src="https://images.unsplash.com/photo-1531927557220-a9e23c1e4794?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=facearea&facepad=2&w=300&h=300&q=80"
|
||||||
alt="Image Description"
|
alt="Avatar Description"
|
||||||
/>
|
/>
|
||||||
<Avatar
|
<Avatar
|
||||||
src="https://images.unsplash.com/photo-1541101767792-f9b2b1c4f127?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&&auto=format&fit=facearea&facepad=3&w=300&h=300&q=80"
|
src="https://images.unsplash.com/photo-1541101767792-f9b2b1c4f127?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&&auto=format&fit=facearea&facepad=3&w=300&h=300&q=80"
|
||||||
alt="Image Description"
|
alt="Avatar Description"
|
||||||
/>
|
/>
|
||||||
<Avatar
|
<Avatar
|
||||||
src="https://images.unsplash.com/photo-1492562080023-ab3db95bfbce?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=facearea&facepad=2&w=300&h=300&q=80"
|
src="https://images.unsplash.com/photo-1492562080023-ab3db95bfbce?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=facearea&facepad=2&w=300&h=300&q=80"
|
||||||
alt="Image Description"
|
alt="Avatar Description"
|
||||||
/>
|
/>
|
||||||
<span
|
<span
|
||||||
class="inline-flex h-8 w-8 items-center justify-center rounded-full bg-zinc-800 ring-2 ring-white dark:bg-zinc-900 dark:ring-zinc-800"
|
class="inline-flex h-8 w-8 items-center justify-center rounded-full bg-zinc-800 ring-2 ring-white dark:bg-zinc-900 dark:ring-zinc-800"
|
||||||
>
|
>
|
||||||
<span
|
<span
|
||||||
class="text-xs font-medium uppercase leading-none text-white"
|
class="text-xs font-medium uppercase leading-none text-white"
|
||||||
>7k+</span
|
>7k+</span>
|
||||||
>
|
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -94,21 +109,22 @@ const reviews: string = "12.8k";
|
||||||
.fill(0)
|
.fill(0)
|
||||||
.map((_, i) => <FullStar key={i} />)
|
.map((_, i) => <FullStar key={i} />)
|
||||||
}
|
}
|
||||||
|
<!-- Adding additional half-star -->
|
||||||
<HalfStar />
|
<HalfStar />
|
||||||
</div>
|
</div>
|
||||||
<p class="text-neutral-800 dark:text-neutral-200">
|
<p class="text-neutral-800 dark:text-neutral-200">
|
||||||
<span class="font-bold">{rating}</span> / 5
|
<Fragment set:html={rating} />
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="text-sm text-neutral-800 dark:text-neutral-200 sm:ps-5">
|
<div class="text-sm text-neutral-800 dark:text-neutral-200 sm:ps-5">
|
||||||
<p>
|
<p>
|
||||||
From Over <span class="font-bold">{reviews}</span> Reviews
|
<Fragment set:html={reviews} />
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div> ) : "" }
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Hero Image Section -->
|
<!-- Hero Image Section -->
|
|
@ -2,10 +2,15 @@
|
||||||
// Import the necessary dependencies
|
// Import the necessary dependencies
|
||||||
import GithubBtn from "../ui/buttons/GithubBtn.astro";
|
import GithubBtn from "../ui/buttons/GithubBtn.astro";
|
||||||
|
|
||||||
// Define the variables that will be used in this component
|
// Define props from Astro
|
||||||
const title: string = "Let's Build Together";
|
const { title, subTitle, url } = Astro.props;
|
||||||
const subTitle: string =
|
|
||||||
"ScrewFast is an open-source template, meticulously crafted with Astro, Tailwind CSS, and Preline UI frameworks.";
|
// Define TypeScript interface for props
|
||||||
|
interface Props {
|
||||||
|
title: string;
|
||||||
|
subTitle: string;
|
||||||
|
url?: string;
|
||||||
|
}
|
||||||
---
|
---
|
||||||
|
|
||||||
<section class="relative mx-auto max-w-[85rem] px-4 pb-24 pt-10 sm:px-6 lg:px-8">
|
<section class="relative mx-auto max-w-[85rem] px-4 pb-24 pt-10 sm:px-6 lg:px-8">
|
||||||
|
@ -14,7 +19,6 @@ const subTitle: string =
|
||||||
class="absolute left-0 top-[55%] scale-90 md:top-[20%] xl:left-[10%] xl:top-[25%]"
|
class="absolute left-0 top-[55%] scale-90 md:top-[20%] xl:left-[10%] xl:top-[25%]"
|
||||||
>
|
>
|
||||||
<svg
|
<svg
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
width="64"
|
width="64"
|
||||||
height="64"
|
height="64"
|
||||||
fill="none"
|
fill="none"
|
||||||
|
@ -45,7 +49,6 @@ const subTitle: string =
|
||||||
</div>
|
</div>
|
||||||
<div class="absolute left-[85%] top-0 scale-75">
|
<div class="absolute left-[85%] top-0 scale-75">
|
||||||
<svg
|
<svg
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
width="64"
|
width="64"
|
||||||
height="64"
|
height="64"
|
||||||
fill="none"
|
fill="none"
|
||||||
|
@ -88,7 +91,6 @@ const subTitle: string =
|
||||||
class="absolute bottom-[5%] left-[60%] scale-[.6] xl:bottom-[15%] xl:left-[35%]"
|
class="absolute bottom-[5%] left-[60%] scale-[.6] xl:bottom-[15%] xl:left-[35%]"
|
||||||
>
|
>
|
||||||
<svg
|
<svg
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
width="64"
|
width="64"
|
||||||
height="64"
|
height="64"
|
||||||
fill="none"
|
fill="none"
|
||||||
|
@ -126,6 +128,6 @@ const subTitle: string =
|
||||||
</div>
|
</div>
|
||||||
<!-- Github Button -->
|
<!-- Github Button -->
|
||||||
<div class="mt-8 flex justify-center gap-3">
|
<div class="mt-8 flex justify-center gap-3">
|
||||||
<GithubBtn url="https://github.com/mearashadowfax/ScrewFast" />
|
<GithubBtn url={url} />
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
|
@ -1,4 +1,5 @@
|
||||||
---
|
---
|
||||||
|
import { Image } from "astro:assets";
|
||||||
// Define constants for content
|
// Define constants for content
|
||||||
const title: string = "Fast-Track Your Projects";
|
const title: string = "Fast-Track Your Projects";
|
||||||
const subTitle: string =
|
const subTitle: string =
|
||||||
|
@ -99,10 +100,11 @@ const statistics: StatProps[] = [
|
||||||
<footer class="mt-6">
|
<footer class="mt-6">
|
||||||
<div class="flex items-center">
|
<div class="flex items-center">
|
||||||
<div class="flex-shrink-0">
|
<div class="flex-shrink-0">
|
||||||
<img
|
<Image
|
||||||
class="h-8 w-8 rounded-full"
|
class="h-8 w-8 rounded-full"
|
||||||
src={testimonial.avatarSrc}
|
src={testimonial.avatarSrc}
|
||||||
alt="Image Description"
|
alt="Avatar Description"
|
||||||
|
inferSize
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div class="ms-4 grow">
|
<div class="ms-4 grow">
|
|
@ -1,4 +1,5 @@
|
||||||
---
|
---
|
||||||
|
import { Image } from "astro:assets";
|
||||||
// Destructure the properties from Astro.props
|
// Destructure the properties from Astro.props
|
||||||
const { src, alt } = Astro.props;
|
const { src, alt } = Astro.props;
|
||||||
|
|
||||||
|
@ -9,9 +10,10 @@ interface Props {
|
||||||
}
|
}
|
||||||
---
|
---
|
||||||
|
|
||||||
<img
|
<Image
|
||||||
class="inline-block h-8 w-8 rounded-full ring-2 ring-neutral-50 dark:ring-zinc-800"
|
class="inline-block h-8 w-8 rounded-full ring-2 ring-neutral-50 dark:ring-zinc-800"
|
||||||
src={src}
|
src={src}
|
||||||
alt={alt}
|
alt={alt}
|
||||||
loading="lazy"
|
inferSize
|
||||||
|
loading={"eager"}
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
// Import necessary components and utilities
|
// Import necessary components and utilities
|
||||||
import AvatarBlog from "../avatars/AvatarBlog.astro";
|
import AvatarBlog from "../avatars/AvatarBlog.astro";
|
||||||
import { Image } from "astro:assets";
|
import { Image } from "astro:assets";
|
||||||
import { formatDate } from "../../../utils";
|
import { formatDate } from "../../../utils/utils";
|
||||||
import type { CollectionEntry } from "astro:content";
|
import type { CollectionEntry } from "astro:content";
|
||||||
|
|
||||||
// Define data sources from Astro props
|
// Define data sources from Astro props
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
---
|
---
|
||||||
// Import necessary modules and utilities
|
// Import necessary modules and utilities
|
||||||
import { Image } from "astro:assets";
|
import { Image } from "astro:assets";
|
||||||
import { formatDate } from "../../../utils";
|
import { formatDate } from "../../../utils/utils";
|
||||||
import type { CollectionEntry } from "astro:content";
|
import type { CollectionEntry } from "astro:content";
|
||||||
// Define data source from Astro.js incoming props
|
// Define data source from Astro.js incoming props
|
||||||
const { blogEntry } = Astro.props;
|
const { blogEntry } = Astro.props;
|
||||||
|
|
|
@ -4,7 +4,7 @@ import Meta from "../components/Meta.astro";
|
||||||
import Navbar from "../components/sections/Navbar.astro";
|
import Navbar from "../components/sections/Navbar.astro";
|
||||||
import FooterSection from "../components/sections/FooterSection.astro";
|
import FooterSection from "../components/sections/FooterSection.astro";
|
||||||
|
|
||||||
// Setting expected props - expecting 'title' and 'meta' as options with a default value for title
|
// Setting expected props
|
||||||
const { title = "ScrewFast", meta, structuredData } = Astro.props;
|
const { title = "ScrewFast", meta, structuredData } = Astro.props;
|
||||||
|
|
||||||
// Interface to type-check the properties
|
// Interface to type-check the properties
|
||||||
|
|
|
@ -12,9 +12,7 @@ const btnTitle: string = "Go Back";
|
||||||
---
|
---
|
||||||
|
|
||||||
<MainLayout
|
<MainLayout
|
||||||
title="Page Not Found | ScrewFast"
|
title="Page Not Found | ScrewFast">
|
||||||
meta="ScrewFast offers top-tier hardware tools and expert construction services to meet all your project needs. Start exploring and contact our sales team for superior quality and reliability."
|
|
||||||
>
|
|
||||||
<section class="grid h-svh place-content-center">
|
<section class="grid h-svh place-content-center">
|
||||||
<div class="mx-auto max-w-screen-xl px-4 py-8 lg:px-6 lg:py-16">
|
<div class="mx-auto max-w-screen-xl px-4 py-8 lg:px-6 lg:py-16">
|
||||||
<div class="mx-auto max-w-screen-sm text-center">
|
<div class="mx-auto max-w-screen-sm text-center">
|
||||||
|
|
|
@ -4,7 +4,7 @@ import MainLayout from "../../layouts/MainLayout.astro";
|
||||||
import AvatarBlogLarge from "../../components/ui/avatars/AvatarBlogLarge.astro";
|
import AvatarBlogLarge from "../../components/ui/avatars/AvatarBlogLarge.astro";
|
||||||
import CardRelated from "../../components/ui/cards/CardRelated.astro";
|
import CardRelated from "../../components/ui/cards/CardRelated.astro";
|
||||||
import { Image } from "astro:assets";
|
import { Image } from "astro:assets";
|
||||||
import { capitalize, formatDate } from "../../utils";
|
import { capitalize, formatDate } from "../../utils/utils";
|
||||||
import { getCollection } from "astro:content";
|
import { getCollection } from "astro:content";
|
||||||
import type { CollectionEntry } from "astro:content";
|
import type { CollectionEntry } from "astro:content";
|
||||||
|
|
||||||
|
@ -30,10 +30,7 @@ const relatedPosts: CollectionEntry<"blog">[] = blogPosts.filter(
|
||||||
);
|
);
|
||||||
---
|
---
|
||||||
|
|
||||||
<MainLayout
|
<MainLayout title={post.data.title + " | ScrewFast"}>
|
||||||
title={post.data.title + " | ScrewFast"}
|
|
||||||
meta="ScrewFast offers top-tier hardware tools and expert construction services to meet all your project needs. Start exploring and contact our sales team for superior quality and reliability."
|
|
||||||
>
|
|
||||||
<section class="mx-auto max-w-3xl px-4 pb-12 pt-6 sm:px-6 lg:px-8 lg:pt-10">
|
<section class="mx-auto max-w-3xl px-4 pb-12 pt-6 sm:px-6 lg:px-8 lg:pt-10">
|
||||||
<div class="max-w-2xl">
|
<div class="max-w-2xl">
|
||||||
<div class="mb-6 flex items-center justify-between">
|
<div class="mb-6 flex items-center justify-between">
|
||||||
|
|
|
@ -29,10 +29,7 @@ const secondSubTitle: string =
|
||||||
"Stay up-to-date with the latest trends and developments in the construction industry with insights from ScrewFast's team of industry experts. ";
|
"Stay up-to-date with the latest trends and developments in the construction industry with insights from ScrewFast's team of industry experts. ";
|
||||||
---
|
---
|
||||||
|
|
||||||
<MainLayout
|
<MainLayout title="Blog | ScrewFast">
|
||||||
title="Blog | ScrewFast"
|
|
||||||
meta="ScrewFast offers top-tier hardware tools and expert construction services to meet all your project needs. Start exploring and contact our sales team for superior quality and reliability."
|
|
||||||
>
|
|
||||||
<section
|
<section
|
||||||
class="mx-auto max-w-[85rem] space-y-8 px-4 pt-16 sm:px-6 lg:px-8 2xl:max-w-full"
|
class="mx-auto max-w-[85rem] space-y-8 px-4 pt-16 sm:px-6 lg:px-8 2xl:max-w-full"
|
||||||
>
|
>
|
||||||
|
|
|
@ -5,9 +5,6 @@ import ContactSection from "../components/sections/ContactSection.astro";
|
||||||
---
|
---
|
||||||
|
|
||||||
<!--Utilizing MainLayout for the outer layout of the page, and defining meta for SEO purposes-->
|
<!--Utilizing MainLayout for the outer layout of the page, and defining meta for SEO purposes-->
|
||||||
<MainLayout
|
<MainLayout title="Contact | ScrewFast">
|
||||||
title="Contact | ScrewFast"
|
|
||||||
meta="ScrewFast offers top-tier hardware tools and expert construction services to meet all your project needs. Start exploring and contact our sales team for superior quality and reliability."
|
|
||||||
>
|
|
||||||
<ContactSection />
|
<ContactSection />
|
||||||
</MainLayout>
|
</MainLayout>
|
||||||
|
|
|
@ -1,26 +1,43 @@
|
||||||
---
|
---
|
||||||
// Import the necessary components
|
// Import the necessary components
|
||||||
import MainLayout from "../layouts/MainLayout.astro";
|
import MainLayout from "../layouts/MainLayout.astro";
|
||||||
import HeroSection from "../components/sections/HeroSection.astro";
|
import HeroSection from "../components/sections/landing/HeroSection.astro";
|
||||||
import HeroSectionAlt from "../components/sections/HeroSectionAlt.astro";
|
import HeroSectionAlt from "../components/sections/landing/HeroSectionAlt.astro";
|
||||||
import ClientsSection from "../components/sections/ClientsSection.astro";
|
import ClientsSection from "../components/sections/landing/ClientsSection.astro";
|
||||||
import FeaturesGeneral from "../components/sections/FeaturesGeneral.astro";
|
import FeaturesGeneral from "../components/sections/features/FeaturesGeneral.astro";
|
||||||
import FeaturesNavs from "../components/sections/FeaturesNavs.astro";
|
import FeaturesNavs from "../components/sections/features/FeaturesNavs.astro";
|
||||||
import TestimonialsSection from "../components/sections/TestimonialsSection.astro";
|
import TestimonialsSection from "../components/sections/testimonials/TestimonialsSection.astro";
|
||||||
import PricingSection from "../components/sections/PricingSection.astro";
|
import PricingSection from "../components/sections/pricing/PricingSection.astro";
|
||||||
import FAQ from "../components/sections/FAQ.astro";
|
import FAQ from "../components/sections/FAQ.astro";
|
||||||
---
|
---
|
||||||
|
|
||||||
<!--Utilizing MainLayout for the outer layout of the page, and defining meta for SEO purposes-->
|
<MainLayout>
|
||||||
<MainLayout
|
<HeroSection
|
||||||
meta="ScrewFast offers top-tier hardware tools and expert construction services to meet all your project needs. Start exploring and contact our sales team for superior quality and reliability."
|
title=`Equip Your Projects with <span
|
||||||
>
|
class="text-yellow-500 dark:text-yellow-400">ScrewFast</span>`
|
||||||
<HeroSection />
|
subTitle="Top-quality hardware tools and expert construction services for every project need."
|
||||||
<ClientsSection />
|
primaryBtn="Start Exploring"
|
||||||
|
primaryBtnURL="/products"
|
||||||
|
secondaryBtn="Contact Sales Team"
|
||||||
|
secondaryBtnURL="/contact"
|
||||||
|
withReview={true}
|
||||||
|
rating=`<span class="font-bold">4.8</span> / 5`
|
||||||
|
starCount={4}
|
||||||
|
reviews=`From Over <span class="font-bold">12.8k</span> Reviews`
|
||||||
|
/>
|
||||||
|
|
||||||
|
<ClientsSection
|
||||||
|
title="Trusted by Industry Leaders"
|
||||||
|
subTitle="Experience the reliability chosen by industry giants."
|
||||||
|
/>
|
||||||
<FeaturesGeneral />
|
<FeaturesGeneral />
|
||||||
<FeaturesNavs />
|
<FeaturesNavs />
|
||||||
<TestimonialsSection />
|
<TestimonialsSection />
|
||||||
<PricingSection />
|
<PricingSection />
|
||||||
<FAQ />
|
<FAQ />
|
||||||
<HeroSectionAlt />
|
<HeroSectionAlt
|
||||||
|
title="Let's Build Together"
|
||||||
|
subTitle="ScrewFast is an open-source template, meticulously crafted with Astro, Tailwind CSS, and Preline UI frameworks."
|
||||||
|
url="https://github.com/mearashadowfax/ScrewFast"
|
||||||
|
/>
|
||||||
</MainLayout>
|
</MainLayout>
|
||||||
|
|
|
@ -16,10 +16,7 @@ export async function getStaticPaths() {
|
||||||
const { post } = Astro.props;
|
const { post } = Astro.props;
|
||||||
---
|
---
|
||||||
|
|
||||||
<MainLayout
|
<MainLayout title={post.data.title + " | ScrewFast"}>
|
||||||
title={post.data.title + " | ScrewFast"}
|
|
||||||
meta="ScrewFast offers top-tier hardware tools and expert construction services to meet all your project needs. Start exploring and contact our sales team for superior quality and reliability."
|
|
||||||
>
|
|
||||||
<section class="py-6 sm:py-8 lg:py-12">
|
<section class="py-6 sm:py-8 lg:py-12">
|
||||||
<div class="mx-auto max-w-screen-xl px-4 md:px-8">
|
<div class="mx-auto max-w-screen-xl px-4 md:px-8">
|
||||||
<div class="grid gap-8 md:grid-cols-2 lg:gap-12">
|
<div class="grid gap-8 md:grid-cols-2 lg:gap-12">
|
||||||
|
|
|
@ -24,10 +24,7 @@ export async function getStaticPaths() {
|
||||||
const { product } = Astro.props;
|
const { product } = Astro.props;
|
||||||
---
|
---
|
||||||
|
|
||||||
<MainLayout
|
<MainLayout title={product.data.main.title + " | ScrewFast"}>
|
||||||
title={product.data.main.title + " | ScrewFast"}
|
|
||||||
meta="ScrewFast offers top-tier hardware tools and expert construction services to meet all your project needs. Start exploring and contact our sales team for superior quality and reliability."
|
|
||||||
>
|
|
||||||
<div id="overlay" class="fixed inset-0 bg-neutral-200 dark:bg-neutral-800">
|
<div id="overlay" class="fixed inset-0 bg-neutral-200 dark:bg-neutral-800">
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -300,7 +297,7 @@ const { product } = Astro.props;
|
||||||
addClasses: any,
|
addClasses: any,
|
||||||
removeClasses: any,
|
removeClasses: any,
|
||||||
) {
|
) {
|
||||||
let heading = button.querySelector("h2");
|
let heading = button.querySelector("span");
|
||||||
if (heading) {
|
if (heading) {
|
||||||
heading.classList.remove(...removeClasses);
|
heading.classList.remove(...removeClasses);
|
||||||
heading.classList.add(...addClasses);
|
heading.classList.add(...addClasses);
|
||||||
|
|
|
@ -4,8 +4,8 @@ import MainLayout from "../../layouts/MainLayout.astro";
|
||||||
import PrimaryCTA from "../../components/ui/buttons/PrimaryCTA.astro";
|
import PrimaryCTA from "../../components/ui/buttons/PrimaryCTA.astro";
|
||||||
import CardSmall from "../../components/ui/cards/CardSmall.astro";
|
import CardSmall from "../../components/ui/cards/CardSmall.astro";
|
||||||
import CardWide from "../../components/ui/cards/CardWide.astro";
|
import CardWide from "../../components/ui/cards/CardWide.astro";
|
||||||
import FeaturesStatsAlt from "../../components/sections/FeaturesStatsAlt.astro";
|
import FeaturesStatsAlt from "../../components/sections/features/FeaturesStatsAlt.astro";
|
||||||
import TestimonialsSectionAlt from "../../components/sections/TestimonialsSectionAlt.astro";
|
import TestimonialsSectionAlt from "../../components/sections/testimonials/TestimonialsSectionAlt.astro";
|
||||||
|
|
||||||
// Importing necessary functions from Astro
|
// Importing necessary functions from Astro
|
||||||
import { getCollection } from "astro:content";
|
import { getCollection } from "astro:content";
|
||||||
|
@ -25,7 +25,7 @@ const subTitle: string =
|
||||||
"Explore the durability and precision of ScrewFast tools, designed for both professionals and enthusiasts. Each of our products is crafted with precision and built to last, ensuring you have the right tool for every job.";
|
"Explore the durability and precision of ScrewFast tools, designed for both professionals and enthusiasts. Each of our products is crafted with precision and built to last, ensuring you have the right tool for every job.";
|
||||||
---
|
---
|
||||||
|
|
||||||
<!--Utilizing MainLayout for the outer layout of the page, and defining meta for SEO purposes-->
|
|
||||||
<MainLayout title="Products | ScrewFast">
|
<MainLayout title="Products | ScrewFast">
|
||||||
<div
|
<div
|
||||||
class="mx-auto max-w-[85rem] px-4 py-10 sm:px-6 lg:px-8 lg:py-14 2xl:max-w-full"
|
class="mx-auto max-w-[85rem] px-4 py-10 sm:px-6 lg:px-8 lg:py-14 2xl:max-w-full"
|
||||||
|
|
|
@ -17,11 +17,7 @@ import progressBuilding from "../images/progress-building.avif";
|
||||||
import underConstruction from "../images/under-construction.avif";
|
import underConstruction from "../images/under-construction.avif";
|
||||||
---
|
---
|
||||||
|
|
||||||
<!--Utilizing MainLayout for the outer layout of the page, and defining meta for SEO purposes-->
|
<MainLayout title="Services | ScrewFast">
|
||||||
<MainLayout
|
|
||||||
title="Services | ScrewFast"
|
|
||||||
meta="ScrewFast offers top-tier hardware tools and expert construction services to meet all your project needs. Start exploring and contact our sales team for superior quality and reliability."
|
|
||||||
>
|
|
||||||
<!--MainSection is the introductory section of the page, it also contains a CTA button-->
|
<!--MainSection is the introductory section of the page, it also contains a CTA button-->
|
||||||
<MainSection
|
<MainSection
|
||||||
title="Uniting Expertise with Your Vision"
|
title="Uniting Expertise with Your Vision"
|
||||||
|
|
36
src/utils/navigation.ts
Normal file
36
src/utils/navigation.ts
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
// An array of links for navigation bar
|
||||||
|
export const navBarLinks = [
|
||||||
|
{ name: "Home", url: "/" },
|
||||||
|
{ name: "Products", url: "/products" },
|
||||||
|
{ name: "Services", url: "/services" },
|
||||||
|
{ name: "Blog", url: "/blog" },
|
||||||
|
{ name: "Contact", url: "/contact" },
|
||||||
|
];
|
||||||
|
// An array of links for footer
|
||||||
|
export const footerLinks = [
|
||||||
|
{
|
||||||
|
section: "Product",
|
||||||
|
links: [
|
||||||
|
{ name: "Tools & Equipment", url: "/products" },
|
||||||
|
{ name: "Construction Services", url: "/services" },
|
||||||
|
{ name: "Pricing", url: "/#" },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
section: "Company",
|
||||||
|
links: [
|
||||||
|
{ name: "About us", url: "#" },
|
||||||
|
{ name: "Blog", url: "#" },
|
||||||
|
{ name: "Careers", url: "#" },
|
||||||
|
{ name: "Customers", url: "#" },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
];
|
||||||
|
// An object of links for social icons
|
||||||
|
export const socialLinks = {
|
||||||
|
facebook: "#",
|
||||||
|
x: "#",
|
||||||
|
github: "https://github.com/mearashadowfax/ScrewFast",
|
||||||
|
google: "#",
|
||||||
|
slack: "#",
|
||||||
|
};
|
Loading…
Add table
Reference in a new issue