Official website for Drift Lab - Autonomous Vehicles Research Laboratory at CAMPUS Research Institute, Politehnica University of Bucharest.
Live Site: https://driftlab.ro
- Features
- Tech Stack
- Project Structure
- Prerequisites
- Installation
- Development
- Adding/Modifying Members
- How the Code Works
- Building for Production
- Deployment
- SEO & Performance
- Key Features Explained
- Configuration Files
- Troubleshooting
- Contributing
- Interactive Galaxy Animation: Procedurally generated spiral galaxy using Three.js with realistic physics-based motion
- Responsive Design: Fully responsive layout optimized for mobile, tablet, and desktop devices
- SEO Optimized: Comprehensive meta tags, Open Graph, Twitter Cards, and structured data (JSON-LD)
- Performance Optimized: Image optimization, lazy loading, font optimization, and resource hints
- Member Management: Easy-to-update JSON-based member directory with photo support
- Team Showcase: Display of multiple research teams with custom styling
- Modern UI: Glassmorphism effects, smooth animations, and gradient accents
- Framework: Astro 5.16.4 - Static site generator with component islands
- 3D Graphics: Three.js 0.182.0 - WebGL-based galaxy animation
- Language: TypeScript - Type-safe development
- Styling: CSS with CSS Variables - Component-scoped styles
- Deployment: GitHub Pages via GitHub Actions
- CI/CD: GitHub Actions with version tag triggers
drift-lab-website/
├── .github/
│ └── workflows/
│ └── deploy.yml # GitHub Actions deployment workflow
├── public/
│ ├── CNAME # Custom domain configuration
│ ├── robots.txt # SEO robots file
│ ├── images/ # Static images (logos, member photos)
│ └── *.png, *.svg # Public assets
├── src/
│ ├── components/
│ │ ├── Footer.astro # Site footer component
│ │ ├── GalaxySystem.ts # Three.js galaxy animation system
│ │ ├── Header.astro # Navigation header
│ │ ├── Hero.astro # Landing section with galaxy
│ │ ├── MembersSection.astro # Member directory display
│ │ └── TeamsSection.astro # Teams showcase
│ ├── data/
│ │ └── members.json # Member data (JSON)
│ ├── layouts/
│ │ └── Layout.astro # Base layout with SEO
│ ├── pages/
│ │ ├── index.astro # Homepage
│ │ └── contact.astro # Contact page
│ └── styles/
│ └── global.css # Global styles and CSS variables
├── astro.config.mjs # Astro configuration
├── package.json # Dependencies and scripts
├── tsconfig.json # TypeScript configuration
└── README.md # This file
src/components/: Reusable Astro components for different sectionssrc/data/: JSON data files (members, teams, etc.)src/layouts/: Base page layouts with shared HTML structuresrc/pages/: Route pages (each.astrofile becomes a route)src/styles/: Global CSS and design tokenspublic/: Static assets served as-is (images, fonts, etc.)
- Node.js: Version 20 or higher
- npm: Comes with Node.js (or use yarn/pnpm)
- Git: For version control
-
Clone the repository:
git clone https://github.com/your-username/drift-lab-website.git cd drift-lab-website -
Install dependencies:
npm install
-
Verify installation:
npm run dev
The development server should start at
http://localhost:4321
Start the local development server with hot reload:
npm run devThe site will be available at http://localhost:4321. Changes to files will automatically reload in the browser.
npm run dev- Start development server with hot reloadnpm run build- Build the site for production (outputs todist/)npm run preview- Preview the production build locallynpm run astro- Run Astro CLI commands
- Make changes to source files in
src/ - The dev server automatically rebuilds and refreshes
- Test changes in the browser
- Commit changes to git
- Push to repository
- Create version tag to trigger deployment
Members are managed through a simple JSON file located at src/data/members.json.
Each member entry follows this structure:
{
"name": "Full Name",
"shortDesc": "Brief description or bio",
"team": "Team Name",
"role": "Role or responsibilities",
"photoLink": "filename.jpg",
"isSupervisor": false
}name(required): Full name of the membershortDesc(required): Brief biography or description. Supports multi-line text with\nteam(required): Team name(s). Can be comma-separated for multiple teams (e.g., "PULSAR, TechTrax")- Valid team names:
PULSAR,Pulsar,TechTrax,Bosch Future Mobility,NXP Cup
- Valid team names:
role(required): Role or responsibilities (e.g., "Software", "Hardware Electronics, Embedded Software")photoLink(optional): Filename of the member's photo- If empty string
"", the system generates a filename from the member's name - If provided, should be just the filename (e.g.,
"petrea-costel-valentin.jpg") - Photos should be placed in
public/images/members/
- If empty string
isSupervisor(required): Boolean indicating if member is a supervisortrue: Member appears in "Laboratory Supervisors" sectionfalse: Member appears in "Team Members" section
-
Add photo (optional):
- Place the photo in
public/images/members/ - Recommended filename format:
firstname-lastname.jpg(lowercase, hyphens) - Supported formats: JPG, PNG, WebP
- Recommended size: 300x300px or square aspect ratio
- Place the photo in
-
Edit
src/data/members.json:{ "name": "John Doe", "shortDesc": "Computer Science student passionate about autonomous systems.", "team": "TechTrax", "role": "Software", "photoLink": "john-doe.jpg", "isSupervisor": false } -
Save the file - The dev server will automatically reload
Simply edit the corresponding entry in src/data/members.json. Changes will appear immediately in development.
The system handles photos with the following logic:
-
If
photoLinkis empty (""):- Generates filename from member name:
john-doe.jpg - Looks for:
public/images/members/john-doe.jpg
- Generates filename from member name:
-
If
photoLinkis a filename (e.g.,"photo.jpg"):- Uses the filename directly
- Looks for:
public/images/members/photo.jpg
-
If
photoLinkis a URL (starts withhttp):- Generates filename from member name (same as empty case)
- Note: URLs are not directly supported; download and save locally
{
"name": "Petrea Costel Valentin",
"shortDesc": "3rd Year Mechatronics & Robotics Student. Embedded Systems, CAD, Big fan of troubleshooting and fixing broken tech.",
"team": "Pulsar",
"role": "Hardware Mechanical",
"photoLink": "petrea-costel-valentin.jpg",
"isSupervisor": false
}This site uses Astro, a modern static site generator that combines the best of static and dynamic rendering. Astro components are written in .astro files, which combine HTML, CSS, and JavaScript/TypeScript in a single file.
The site follows a component-based architecture:
Layout.astro (Base Layout)
├── Header.astro (Navigation)
├── Hero.astro (Landing Section)
│ └── GalaxySystem.ts (Three.js Animation)
├── TeamsSection.astro (Teams Display)
├── MembersSection.astro (Members Display)
└── Footer.astro (Footer)
members.json → MembersSection.astro → index.astro → Layout.astro → HTML Output
- Data Layer:
src/data/members.jsonstores member information - Component Layer:
MembersSection.astroreads and processes the JSON - Page Layer:
index.astroimports and renders components - Layout Layer:
Layout.astrowraps pages with common HTML structure - Output: Astro generates static HTML files
- Base HTML structure with
<head>and<body> - SEO meta tags (Open Graph, Twitter Cards, canonical URLs)
- Structured data (JSON-LD schemas)
- Resource hints (preconnect, dns-prefetch)
- Global CSS import
- Fixed navigation bar
- Smooth scroll navigation for anchor links
- Mobile-responsive hamburger menu
- Logo and navigation links
- Landing section with hero text
- Integrates
GalaxySystem.tsfor background animation - Call-to-action buttons
- Partner logos display
- Three.js-based procedural galaxy generator
- Creates realistic spiral galaxy with physics-based motion
- Performance optimizations:
- Device-specific particle counts (mobile: 30%, tablet: 60%, desktop: 100%)
- Visibility API pauses animation when tab is hidden
- Responsive camera positioning
- Optimized rendering settings
- Displays research teams in a grid layout
- Team data defined inline in the component
- Custom color accents per team
- Responsive card design
- Reads
members.jsonand filters byisSupervisor - Renders supervisors and regular members separately
- Interactive member cards with modal popup
- Image path resolution logic
- Responsive grid layout
- CSS Variables: Defined in
src/styles/global.cssfor consistent theming - Component Styles: Scoped styles in each
.astrocomponent - Responsive Design: Uses
clamp()for fluid typography and spacing - Design System: Color tokens, spacing scale, border radius values
The galaxy animation is integrated as follows:
- Component:
Hero.astroincludes a<canvas>element - Script: Client-side script imports
GalaxySystem.ts - Initialization: Creates
GalaxySysteminstance on page load - Cleanup: Properly destroys instance on page unload
The animation runs entirely client-side and doesn't require server-side rendering.
npm run buildThis command:
- Compiles all Astro components to static HTML
- Processes and optimizes images
- Bundles JavaScript and CSS
- Generates sitemap.xml
- Outputs everything to
dist/directory
The dist/ directory contains:
- Static HTML files
- Optimized CSS and JavaScript bundles
- Processed images
sitemap-index.xmlandsitemap-0.xmlCNAMEfile (for custom domain)
- CSS: Inline critical stylesheets automatically
- JavaScript: Minified and bundled
- Images: Optimized and compressed
- HTML: Minified output
- Assets: Hashed filenames for cache busting
Before deploying, preview the production build locally:
npm run build
npm run previewThis serves the dist/ directory locally so you can verify everything works correctly.
The site is deployed to GitHub Pages using GitHub Actions. Deployment is triggered automatically when a version tag is pushed to the repository.
-
Create version tag:
git tag v1.0.0 git push origin v1.0.0
-
GitHub Actions triggers:
- Workflow runs on tag push matching
v*.*.*pattern - Builds the site using Node.js 20
- Deploys to GitHub Pages
- Workflow runs on tag push matching
-
Site goes live:
- Available at
https://driftlab.ro(after DNS propagation) - Usually takes 2-5 minutes after workflow completes
- Available at
Use semantic versioning:
- Major (
v1.0.0): Breaking changes or major updates - Minor (
v1.1.0): New features, backward compatible - Patch (
v1.0.1): Bug fixes, small improvements
Example workflow:
# Make changes and commit
git add .
git commit -m "Add new team member"
git push origin main
# Create and push version tag
git tag v1.0.1
git push origin v1.0.1- Go to repository Settings → Pages
- Source: Select "GitHub Actions"
- Custom domain: Enter
driftlab.ro - Enforce HTTPS: Enable (recommended)
The public/CNAME file contains driftlab.ro and is automatically deployed.
DNS Configuration (at your domain registrar):
Option A: A Records (for root domain):
@ → 185.199.108.153
@ → 185.199.109.153
@ → 185.199.110.153
@ → 185.199.111.153
Option B: CNAME (if supported):
@ → yourusername.github.io
For www subdomain:
www → yourusername.github.io (CNAME)
Wait for DNS propagation (5 minutes to 48 hours), then verify at https://driftlab.ro.
The workflow file (.github/workflows/deploy.yml) handles:
- Trigger: Version tags (
v*.*.*) - Build: Installs dependencies, builds site
- Deploy: Uploads to GitHub Pages
- Permissions: Configured for GitHub Pages deployment
- Meta Tags: Title, description, keywords, author
- Open Graph: Facebook/LinkedIn sharing optimization
- Twitter Cards: Twitter sharing optimization
- Structured Data: JSON-LD schemas for:
- Organization
- WebSite
- ResearchProject
- ContactPage
- LocalBusiness
- Sitemap: Automatically generated XML sitemap
- Robots.txt: Search engine crawler instructions
- Canonical URLs: Prevents duplicate content issues
- Image Optimization: Width/height attributes, lazy loading
- Font Optimization: Preconnect hints,
display=swap - Resource Hints: Preload critical resources, dns-prefetch
- Code Splitting: Automatic code splitting by Astro
- Minification: CSS and JavaScript minified in production
- Three.js Optimization: Device-specific rendering, visibility API
The site is optimized for:
- LCP (Largest Contentful Paint): Optimized images and fonts
- FID (First Input Delay): Minimal JavaScript blocking
- CLS (Cumulative Layout Shift): Proper image dimensions
The galaxy animation (GalaxySystem.ts) creates a procedurally generated spiral galaxy:
How it works:
- Generates particles in a logarithmic spiral pattern
- Applies realistic density distribution (more particles near center)
- Implements differential rotation (inner particles orbit faster)
- Adds velocity dispersion for realism
- Uses additive blending for starlight accumulation
Performance Optimizations:
- Device Detection: Reduces particle count on mobile (30%) and tablet (60%)
- Visibility API: Pauses animation when browser tab is hidden
- Pixel Ratio: Limits pixel ratio based on device
- Camera Optimization: Adjusts FOV and position per device
Technical Details:
- Uses Three.js Sprites for efficient rendering
- Implements realistic orbital mechanics
- Creates 4 spiral arms with configurable parameters
- Color gradient from center (bright blue) to edges (darker blue)
- Mobile-First: Designed for mobile, enhanced for larger screens
- Fluid Typography: Uses
clamp()for responsive text sizes - Flexible Layouts: CSS Grid and Flexbox for adaptive layouts
- Touch-Friendly: Large tap targets, smooth scrolling
- Lazy Loading: Images load as user scrolls
- Proper Dimensions: Width/height attributes prevent layout shift
- Optimized Formats: Supports WebP/AVIF (via Astro Image component)
- Responsive Images: Different sizes for different viewports
Main Astro configuration:
- site: Production URL (
https://driftlab.ro) - integrations: Sitemap generation
- server: Development server settings
- build: Build optimizations
Dependencies and scripts:
- dependencies: Astro, Three.js, sitemap integration
- devDependencies: TypeScript types
- scripts: Development and build commands
TypeScript configuration:
- Extends Astro's strict TypeScript config
- Includes all
.astrofiles - Excludes
dist/directory
GitHub Actions workflow:
- Triggers on version tags
- Builds and deploys to GitHub Pages
- Configured with proper permissions
Issue: Port 4321 already in use
Solution:
# Kill process on port 4321 (Windows)
netstat -ano | findstr :4321
taskkill /PID <PID> /F
# Or use a different port
npm run dev -- --port 3000Issue: Build errors or missing dependencies
Solution:
# Clear node_modules and reinstall
rm -rf node_modules package-lock.json
npm install
# Check Node.js version (should be 20+)
node --versionIssue: Member photos not displaying
Solution:
- Verify photo exists in
public/images/members/ - Check filename matches
photoLinkin JSON (case-sensitive) - Ensure file extension is correct (.jpg, .png, etc.)
- Check browser console for 404 errors
Issue: Three.js animation doesn't appear
Solution:
- Check browser console for errors
- Verify WebGL is supported (most modern browsers)
- Check if JavaScript is enabled
- Try disabling browser extensions
- Verify Three.js is installed:
npm list three
Issue: GitHub Actions workflow fails
Solution:
- Check workflow logs in GitHub Actions tab
- Verify Node.js version in workflow matches local
- Ensure all dependencies are in
package.json - Check for syntax errors in code
- Verify GitHub Pages is enabled in repository settings
Issue: Site doesn't load at driftlab.ro
Solution:
- Verify DNS records are correct (use
dig driftlab.roornslookup driftlab.ro) - Check CNAME file exists in
public/CNAME - Wait for DNS propagation (can take up to 48 hours)
- Verify domain is configured in GitHub Pages settings
- Check SSL certificate status in GitHub Pages settings
- Fork the repository
- Create a feature branch:
git checkout -b feature/your-feature-name
- Make your changes
- Test locally:
npm run dev npm run build
- Commit your changes:
git commit -m "Add: description of changes" - Push to your fork:
git push origin feature/your-feature-name
- Create a Pull Request
- TypeScript: Use TypeScript for type safety
- Formatting: Follow existing code style
- Components: Keep components focused and reusable
- Comments: Add comments for complex logic
- Naming: Use descriptive variable and function names
- Ensure your code builds successfully (
npm run build) - Test all functionality locally
- Update documentation if needed
- Create a clear PR description
- Wait for review and feedback
This project is proprietary and belongs to Drift Lab, CAMPUS Research Institute, Politehnica University of Bucharest.
- Framework: Built with Astro
- 3D Graphics: Powered by Three.js
- Deployment: Hosted on GitHub Pages
- Design: Custom design by Drift Lab team
For questions or issues, please open an issue on GitHub or contact the lab administrators.