Official website for the CVAR-UPM Drone Team, developed with Astro. This repository contains all information about the team, competitions, divisions, and members.
Visit the website: https://cvar-upm.github.io/drone_team_web/
- Project Structure
- Technologies Used
- Installation and Setup
- Available Commands
- Guide to Adding Content
- Available Components
- Styles and Themes
- Deployment
drone_team_web/
├── public/ # Static files (images, videos, logos)
│ ├── a2rl25/ # A2RL Season 1 images
│ ├── a2rl26/ # A2RL Season 2 images
│ ├── icuas22/ # ICUAS 2022 images
│ ├── icuas23/ # ICUAS 2023 images
│ ├── imav19/ # IMAV 2019 images
│ ├── imav22/ # IMAV 2022 images
│ ├── imav25/ # IMAV 2025 images
│ ├── mbzirc/ # MBZIRC images
│ ├── members/ # Team member photos
│ ├── divisions/ # Division images
│ ├── logo-cvar.png # Team logo
│ ├── aerostack2.svg # Aerostack2 logo
│ └── ... # Other logos and resources
├── src/
│ ├── assets/ # Assets processed by Astro
│ ├── components/ # Reusable components
│ │ ├── Carousel.astro # Image/video carousel
│ │ ├── Footer.astro # Footer with social media links
│ │ ├── Header.astro # Header with logo and title
│ │ ├── Image.astro # Component to display images
│ │ ├── Member.astro # Team member card
│ │ ├── Navigation.astro # Navigation menu
│ │ ├── Row.astro # Grid row for members
│ │ ├── SideImage.astro # Section with image and side logo
│ │ ├── SideSection.astro # Section with image and side text
│ │ ├── Social.astro # Social media links
│ │ └── Video.astro # Component for videos (iframe or local)
│ ├── layouts/
│ │ └── Layout.astro # Main page layout
│ ├── pages/ # Site pages (automatic routes)
│ │ ├── index.astro # Home page
│ │ ├── members.astro # Members page
│ │ ├── competitions.astro # Main competitions page
│ │ ├── divisions.astro # Divisions page
│ │ ├── contact.astro # Contact page
│ │ └── competitions/ # Competition subpages
│ │ ├── A2RL.astro # A2RL details
│ │ ├── ICUAS.astro # ICUAS details
│ │ ├── IMAV.astro # IMAV details
│ │ ├── MBZIRC.astro # MBZIRC details
│ │ └── OpenCV.astro # OpenCV details
│ └── styles/
│ └── global.css # Global site styles
├── astro.config.mjs # Astro configuration
├── package.json # Project dependencies
└── README.md # This file
- Astro 5.17.1: Main framework for the static site
- Node.js: JavaScript runtime environment
- CSS3: Custom styles with CSS variables
- HTML5: Semantic structure
- Node.js (version 18 or higher)
- npm (included with Node.js)
- Clone the repository:
git clone https://github.com/cvar-upm/drone_team_web.git
cd drone_team_web- Install dependencies:
npm install- Start the development server:
npm run devThe site will be available at http://localhost:4321/drone_team_web
| Command | Action |
|---|---|
npm install |
Installs all dependencies |
npm run dev |
Starts development server at localhost:4321/drone_team_web |
npm run build |
Builds the site for production in ./dist/ |
npm run preview |
Previews the production build locally |
npm run astro ... |
Runs Astro CLI commands |
-
Add the member's photo:
- Place the image in
/public/members/ - Name the file descriptively (e.g.,
first_last.jpeg)
- Place the image in
-
Edit the members file:
- Open
/src/pages/members.astro - Add the member to the corresponding section (
firstRow,secondRow, etc.):
- Open
const firstRow = [
// ... existing members
{
name: 'Full Name',
image: '/members/first_last.jpeg',
github: 'https://github.com/username', // Optional
linkedin: 'https://www.linkedin.com/in/username/' // Optional
},
];- Member categories:
firstRowandsecondRow: Active MembersthirdRowandfourthRow: CollaboratorsfifthRow: Former Members
Create a folder in /public/ with the competition name and year:
/public/competition_name_year/
Edit /src/pages/competitions.astro and add a SideImage component:
<SideImage
image="/competition_name/main_photo.jpeg"
logoImage="/competition_logo.png"
url={`${import.meta.env.BASE_URL}/competitions/CompetitionName`}
reverse={false} // Alternate true/false to change side
/>Create a file in /src/pages/competitions/CompetitionName.astro:
---
import Layout from '../../layouts/Layout.astro';
import Carousel from '../../components/Carousel.astro';
import '../../styles/global.css';
const items = [
{ type: 'video', src: 'https://player.vimeo.com/video/VIDEO_ID' },
{ type: 'image', src: '/competition_name/image1.jpeg' },
{ type: 'image', src: '/competition_name/image2.jpeg' },
];
---
<Layout
title="Competition Name"
logoImage="/competition_logo.png"
showJoin={false}
heroImage="/competition_name/hero.jpeg"
>
<section id="year">
<h2>Competition Name Year</h2>
<p>
Detailed description of the competition, team achievements,
technologies used, etc.
</p>
<p>
More details at: <a href="OFFICIAL_URL" target="_blank">Official Website</a>
</p>
</section>
<Carousel items={items} />
</Layout>Edit /src/components/Navigation.astro to add the new competition to the dropdown:
<li class="dropdown-submenu">
<a href={`${import.meta.env.BASE_URL}/competitions/CompetitionName`}>Competition Name</a>
<ul class="dropdown-submenu-menu">
<li><a href={`${import.meta.env.BASE_URL}/competitions/CompetitionName#2024`}>2024</a></li>
<li><a href={`${import.meta.env.BASE_URL}/competitions/CompetitionName#2023`}>2023</a></li>
</ul>
</li>- Place the image in
/public/in the corresponding folder - Use the
Imagecomponent:
<Image
imageUrl="/folder/image_name.jpg"
alt="Image description"
title="Optional title"
/>Vimeo/YouTube videos (iframes):
<Video
videoUrl="https://player.vimeo.com/video/VIDEO_ID"
title="Video title"
/>Local videos:
<Video
videoUrl="/folder/video.mp4"
title="Video title"
/>const items = [
{ type: 'video', src: 'https://player.vimeo.com/video/ID' },
{ type: 'image', src: '/folder/image1.jpeg', alt: 'Description' },
{ type: 'image', src: '/folder/image2.jpeg', alt: 'Description' },
];
<Carousel items={items} />Edit /src/pages/divisions.astro and add a new section:
<section id="division-name">
<SideSection
image="/divisions/division_image.png"
title="Division Name"
description={`Detailed description of the division,
its responsibilities, technologies used, etc.`}
reverse={false} // Alternate to change image position
/>
</section>Update the navigation menu in /src/components/Navigation.astro:
<li><a href={`${import.meta.env.BASE_URL}/divisions#division-name`}>Division Name</a></li>Main layout for all pages. Props:
title: Page title (required)subtitle: Subtitle (optional)showJoin: Show "JOIN US" button (boolean)heroImage: Hero background image (optional)logoImage: Logo in the hero (optional)
Fixed header with logo and navigation. Automatically included in the Layout.
Navigation menu with dropdowns. Configured for all site sections.
Footer with:
- Team logo and name
- Social media links (Instagram, LinkedIn, YouTube, Vimeo, GitHub)
- Embedded location map
- Copyright
Image and video carousel. Props:
items: Array of objects withtype,src,alt(optional),title(optional)
Features:
- Arrow navigation
- Clickable indicators
- Support for videos (iframe and local) and images
- Responsive
Displays an image with responsive format. Props:
imageUrl: Image path (required)alt: Alternative texttitle: Image title
Displays videos (iframe or local). Props:
videoUrl: Video URL or local path (required)title: Video title
Automatically detects if it's an iframe (Vimeo, YouTube) or local video.
Team member card. Props:
name: Full name (required)image: Photo path (required)github: GitHub URL (optional)linkedin: LinkedIn URL (optional)
Grid container to display multiple members. Props:
members: Array of member objects
Section with image and side logo/title. Props:
image: Background imagetitle: Title (if no logo)logoImage: Logo to display (optional)url: Link (optional)reverse: Reverse image position (boolean)
Section with image and descriptive side text. Props:
image: Side imagetitle: Section titledescription: Descriptive texturl: Link in the title (optional)reverse: Reverse image position (boolean)
Social media links (simple component). Props:
platform: Platform (e.g., "github")username: Username
The site uses CSS variables defined in /src/styles/global.css:
:root {
--cvar-blue-primary: #0064ab;
--cvar-blue-secondary: #007abe;
--cvar-blue-light: #009bdb;
--cvar-black: #000000;
--cvar-dark-gray: #3e3c3c;
--cvar-white: #ffffff;
}Edit the variables in global.css to change the color palette globally.
Each .astro component can have its own <style> block with scoped or global styles.
The site is configured to deploy on GitHub Pages:
// astro.config.mjs
export default defineConfig({
site: 'https://cvar-upm.github.io',
base: '/drone_team_web',
output: 'static',
});- Build the site:
npm run build-
Generated files will be in
/dist/ -
Configure GitHub Actions or manually deploy the
dist/folder to thegh-pagesbranch
To deploy on Netlify, Vercel, or other platforms:
- Adjust the configuration in
astro.config.mjs:
export default defineConfig({
site: 'https://your-domain.com',
base: '/',
output: 'static',
});- Follow the platform's instructions for deploying static sites
npm updatenpm run buildnpm run build
npm run previewFor more information about the CVAR-UPM Drone Team:
- Instagram: @cvar_upm
- LinkedIn: CVAR-UPM
- YouTube: @CVAR-UPM
- GitHub: aerostack2