An open API service indexing awesome lists of open source software.

https://github.com/skye-flyhigh/flymorocco

just a migration of my old website, from hardcoded HTML CSS JS to modern frameworks Next.js
https://github.com/skye-flyhigh/flymorocco

daisyui-react interactive-map leaflet-map nextjs openair openair-parser pdf-generation useactionstate zod-validation

Last synced: 28 days ago
JSON representation

just a migration of my old website, from hardcoded HTML CSS JS to modern frameworks Next.js

Awesome Lists containing this project

README

          

# πŸͺ‚ FlyMorocco

**Multilingual paragliding hub for pilots exploring the skies of Morocco.**
Built with Next.js, Tailwind CSS, and the occasional chaos-fueled tea session.

---

## πŸš€ Project Overview

Flymorocco is a fully static, SEO-friendly, and i18n-ready web app tailored for paragliding pilots looking to fly in Morocco.
It serves guide pages for multiple flying sites, dynamically rendered and maintained by a single JSON data source, localized in both **English** and **French**.

---

## ✨ Features

### Core Platform

- 🌍 **Multilingual** with `next-intl` (EN/FR)
- πŸͺ **Dynamic site guides** powered by slug-based routing
- πŸ–ΌοΈ **Visual-first layout** to highlight the beauty of flying sites
- πŸ” **SEO-ready** with custom meta tags per page
- πŸ—ΊοΈ **Interactive airspace maps** with Morocco's official ENR 5.5 data

### E-Commerce Booking System

- πŸ’³ **Multi-currency booking** (GBP, USD, EUR, CAD) through Wise
- πŸ‘₯ **Multi-participant support** with pilot detection and verification
- 🏠 **Solo room options** with dynamic pricing calculations
- πŸ“§ **Professional email pipeline** (confirmations, notifications, verifications)
- 🎯 **Marketing-optimized emails** with clickable tour banners
- πŸ“‹ **PDF document generation** for CAA authorization forms
- πŸ§‘β€πŸ’» **Google Spreadsheet integration** for booking management

### Technical Excellence

- βš™οΈ **Type-safe data** validation with Zod schemas
- πŸ”’ **Security features** with reCAPTCHA and input sanitization
- πŸ“± **Responsive design** with accessibility built-in
- πŸš€ **Static generation** for optimal performance

---

## 🧠 Dev Stack

- [Next.js 15](https://nextjs.org/) the goat 🐐
- [Tailwind CSS](https://tailwindcss.com/) the 1000 pieces jigsaw puzzle of styling 🧩
- [DaisyUI](https://daisyui.com/) the picture of the box of the puzzle 🧩
- [Lucide React](https://lucide.dev/) for clean, consistent icons
- [Zod](https://zod.dev/?id=objects) to break my app again
- [React Leaflet](https://react-leaflet.js.org/), who does like a good map?
- [OpenAir parser](https://www.npmjs.com/package/@openaip/openair-parser?activeTab=readme), need content for map
- [pdf-lib](https://www.npmjs.com/package/pdf-lib), advanced pdf generation πŸ“
- [sendGrid](https://www.npmjs.com/package/@sendgrid/mail), to send the advanced pdfs
- [react-scroll-parallax](https://www.npmjs.com/package/react-scroll-parallax), smooth scrolling effects

---

## 🧠 Setup

bash
git clone https://github.com/skye-flyhigh/flymorocco.git
cd flymorocco
npm install
npm run dev

---

## πŸ“‚ Folder Structure Highlights

app/
β”œβ”€β”€ [locale]/
β”‚ β”œβ”€β”€ layout.tsx # Locale-aware layout << Case of the missing E
β”‚ β”œβ”€β”€ page.tsx # Localized homepage
β”‚ β”œβ”€β”€ components/ # πŸͺ„ Magic πŸ’«
β”‚ └── site-guides/ # Dynamic πŸ”οΈ (per location)
β”œβ”€β”€ layout.tsx # Language overlay
β”œβ”€β”€ lib/
β”‚ └── site.ts
β”œβ”€β”€ types/
β”‚ └── siteMeta.ts # Zod's schema validation for site guide meta
β”œβ”€β”€ i18n/ # next-intl language package
└── middleware.ts # i18n routing redirect

The messages folder for the translations are living outside of the src/app folder according to next-intl docs.

πŸ“‚
β”œβ”€β”€ messages/
β”‚ β”œβ”€β”€ en.json
β”‚ └── fr.json
β”œβ”€β”€ public/images/
β”œβ”€β”€ src/app/

---

## πŸ”₯ Developer Lore

> **β€œThe Case of the Missing E”**

During the i18n setup, a rogue param named `local` (missing the "e") hijacked the entire layout and crashed the app via a top-level `await`.
After hours of meticulous logs, terminal therapy, and a _French-accented scream_, the bug was identified.

πŸ§ͺ Resolved by explicitly setting:

const { local: locale } = resolvedParams;
// Official docs said it returns { locale }... THEY LIED. IT'S 'local'.
// Yes, I logged it. Yes, I screamed.

Also the correct solution is in `middleware.ts`, to force the correct `param` key

createMiddleware({
...routing,
localeParam: 'locale' // << WITH a 'e'
})

This project will proudly wear the battle scars of this journey.

> **"πŸ—ΊοΈ The Cartographic Conquest (April 2025)"**

β€œIt started with a file… and ended in 20,000 lines of polygon geometry.”

- Parsed Morocco’s official ENR 5.5 airspaces from OpenAir format using a hacked parser and caffeine-fueled determination
- Resolved cryptic parser errors like "Unknown altitude definition '3500'" and "Token 'DB' does not allow subsequent token 'AY'" by reverse-engineering format expectations
- Used fixGeometry: true to handle self-intersecting madness (and hoped nothing got lost in convex purgatory)
- Successfully converted nested sectors, parachute zones, and TMA fragments into GeoJSON, rendered live with Leaflet
- Deployed hoverable, paintable polygons with visual filtering (GSEC toggle) and type-based coloring

πŸ“Œ Status: All airspaces rendered. CTR drama avoided. Moroccan CAA blocked my IP β€” success confirmed.

πŸ’¬ β€œTurns out drawing maps is harder than flying through them.” β€” Skye

### 🧾 The CAA Form Saga (April 2025)

The CAA submission form was fully implemented using:

- `useActionState` from React 19 for async validation + response control
- Schema-driven layout using Zod and dynamic JSX generation
- Modular error handling with inline accessibility-friendly feedback
- `SiteSelector` custom component for dynamic zone selection
- Locale-aware translation of all labels and placeholders (`next-intl`)
- Future-proofed design for PDF generation and multilingual submission

This form is now the template for any future high-logic form on FlyMorocco or other apps.

πŸ’¬ β€œThe amount of logic this form contains is unhealthy. But it's clean.” β€” Skye

---

## πŸͺ‚ Author

Skye – Paraglider pilot and instructor, Chaos Wielder, Front-End Dev, AI Architect, Mint Tea Enthusiast

---

## πŸ§™β€β™‚οΈ Want to Contribute?

This is a personal dev playground, not open source (yet).
You’re welcome to star, fork, or fly by.

---

Β© 2025 Skye.cmd / FlyMorocco. All rights reserved.
This project is **not open source**. No reuse, redistribution, or derivative works permitted without express permission.