diff --git a/.eslintrc.json b/.eslintrc.json new file mode 100644 index 0000000..bffb357 --- /dev/null +++ b/.eslintrc.json @@ -0,0 +1,3 @@ +{ + "extends": "next/core-web-vitals" +} diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 98e1df5..29e207d 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -10,20 +10,25 @@ jobs: runs-on: ubuntu-latest steps: - - name: Install SSH Key - uses: webfactory/ssh-agent@v0.8.0 + - name: Checkout code + uses: actions/checkout@v2 + + - name: Set up Node.js + uses: actions/setup-node@v2 with: - ssh-private-key: ${{ secrets.PRIVATE_KEY }} + node-version: "20" + + - name: Install dependencies + run: npm install - - name: Deploy to Digital Ocean - run: | - ssh -o StrictHostKeyChecking=no snailbones@104.248.65.121<< 'ENDSSH' - source ~/.nvm/nvm.sh - nvm use 20 - which node - which npm - cd /var/www/forage-abq - git pull origin main - npm install - npm run build - ENDSSH + - name: Build + run: npm run build + + - name: Deploy + uses: appleboy/scp-action@master + with: + host: ${{ secrets.HOST }} + username: ${{ secrets.USERNAME }} + key: ${{ secrets.PRIVATE_KEY }} + source: "./build" + target: "/var/www/forage-abq" diff --git a/.gitignore b/.gitignore index 4d29575..fd3dbb5 100644 --- a/.gitignore +++ b/.gitignore @@ -4,20 +4,33 @@ /node_modules /.pnp .pnp.js +.yarn/install-state.gz # testing /coverage +# next.js +/.next/ +/out/ + # production /build # misc .DS_Store -.env.local -.env.development.local -.env.test.local -.env.production.local +*.pem +# debug npm-debug.log* yarn-debug.log* yarn-error.log* + +# local env files +.env*.local + +# vercel +.vercel + +# typescript +*.tsbuildinfo +next-env.d.ts diff --git a/README.md b/README.md index 32a299c..0dc9ea2 100644 --- a/README.md +++ b/README.md @@ -1,15 +1,36 @@ -# [ForageABQ.com](www.forageabq.com) +This is a [Next.js](https://nextjs.org/) project bootstrapped with [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app). -An interactive guide to common and easily usable edible plants in Albuquerque, NM. +## Getting Started -### to do high priority: +First, run the development server: -- test on mobile -- performance: resize images +```bash +npm run dev +# or +yarn dev +# or +pnpm dev +# or +bun dev +``` -### to do: +Open [http://localhost:3000](http://localhost:3000) with your browser to see the result. -- adding more plants -- adding more images -- visual styling -- scrolling with mouse wheel +You can start editing the page by modifying `app/page.js`. The page auto-updates as you edit the file. + +This project uses [`next/font`](https://nextjs.org/docs/basic-features/font-optimization) to automatically optimize and load Inter, a custom Google Font. + +## Learn More + +To learn more about Next.js, take a look at the following resources: + +- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API. +- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial. + +You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js/) - your feedback and contributions are welcome! + +## Deploy on Vercel + +The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js. + +Check out our [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more details. diff --git a/app/Calendar.scss b/app/Calendar.scss new file mode 100644 index 0000000..e977562 --- /dev/null +++ b/app/Calendar.scss @@ -0,0 +1,11 @@ +@import "styles/variables"; + +.calendar { + padding: 2em; + // background-color: $background-color; + + h2 { + text-align: center; + color: $text-color-light; + } +} diff --git a/app/all-plants/FullPlantList.scss b/app/all-plants/FullPlantList.scss new file mode 100644 index 0000000..3632c22 --- /dev/null +++ b/app/all-plants/FullPlantList.scss @@ -0,0 +1,11 @@ +@import "styles/variables"; + +.calendar { + padding: 2em; + background-color: $background-color; + + h2 { + text-align: center; + color: $text-color-light; + } +} diff --git a/src/components/FullPlantList/index.js b/app/all-plants/page.js similarity index 61% rename from src/components/FullPlantList/index.js rename to app/all-plants/page.js index 74c27fb..9113356 100644 --- a/src/components/FullPlantList/index.js +++ b/app/all-plants/page.js @@ -1,8 +1,10 @@ +"use client"; + import React, { useEffect, useState } from "react"; import YAML from "js-yaml"; -import { loadData } from "../../utils/loadPlantData"; -import { getCurrentMonth } from "../../utils/format"; -import PlantList from "../PlantList/PlantList"; +import { loadData } from "utils/loadPlantData"; +import { getCurrentMonth } from "utils/format"; +import PlantList from "components/PlantList/PlantList"; import "./FullPlantList.scss"; const FullPlantList = () => { @@ -15,18 +17,6 @@ const FullPlantList = () => { const plantListYAML = await plantListResponse.text(); const plantNames = YAML.load(plantListYAML); - // const newPlants = []; - // for (const plantName of plantNames) { - // const plantData = await loadData(plantName); - // plantData.dirName = plantName; - // newPlants.push(plantData); - // } - // const newPlants = plantNames.map((plantName) => { - // const plantData = await loadData(plantName); - // plantData.dirName = plantName; - // return plantData; - // } - const newPlants = await Promise.all( plantNames.map(async (plantName) => { const plantData = await loadData(plantName); diff --git a/public/favicon.ico b/app/favicon.ico similarity index 100% rename from public/favicon.ico rename to app/favicon.ico diff --git a/app/layout.js b/app/layout.js new file mode 100644 index 0000000..46139c7 --- /dev/null +++ b/app/layout.js @@ -0,0 +1,27 @@ +import { Inter } from "next/font/google"; +import "styles/globals.scss"; +import Header from "components/Header"; +import Footer from "components/Footer"; +import NavBar from "components/NavBar"; + +const inter = Inter({ subsets: ["latin"] }); + +export const metadata = { + title: "Forage Albuquerque", + description: "A guide to Albuquerque's edible plants", +}; + +export default function RootLayout({ children }) { + return ( + + +
+
+ +
{children}
+
+ + + ); +} diff --git a/src/components/Calendar/index.js b/app/page.js similarity index 84% rename from src/components/Calendar/index.js rename to app/page.js index ebe0e4b..ad52f22 100644 --- a/src/components/Calendar/index.js +++ b/app/page.js @@ -1,8 +1,11 @@ +/* eslint-disable react/no-unescaped-entities */ +"use client"; + import React, { useEffect, useState } from "react"; import YAML from "js-yaml"; -import { loadData } from "../../utils/loadPlantData"; -import { getCurrentMonth, getMonthName } from "../../utils/format"; -import PlantList from "../PlantList/PlantList"; +import { loadData } from "utils/loadPlantData"; +import { getCurrentMonth, getMonthName } from "utils/format"; +import PlantList from "components/PlantList/PlantList"; import "./Calendar.scss"; const Calendar = () => { diff --git a/app/plant/PlantProfile.scss b/app/plant/PlantProfile.scss new file mode 100644 index 0000000..d48e6ff --- /dev/null +++ b/app/plant/PlantProfile.scss @@ -0,0 +1 @@ +@import "styles/variables"; diff --git a/app/plant/amaranthus/page.mdx b/app/plant/amaranthus/page.mdx new file mode 100644 index 0000000..c5ed2cf --- /dev/null +++ b/app/plant/amaranthus/page.mdx @@ -0,0 +1,13 @@ +# Amaranth + +## _Amaranthus palmeri_ + +While often considered a weed, our common amaranth, _Amaranthus palmeri_ is a native plant, just one that thrives in disturbance.. + +The amaranth family includes spinanch and many of our local wild foods: [Quelites](chenopodium), [Tumbleweed](salsola), [Kochia](bassia). + +Ensure that leaves are dry, then quickly fry them and add a pinch of salt or Tajin for a crunchy snack! Be careful not to burn them. + +Amaranth can accumulate nitrates. Don't harvest if artificial fertilizers have been used. + +C4 photosynthesis allows amaranths to grow faster than other plants and with less water. diff --git a/app/plant/bassia/page.mdx b/app/plant/bassia/page.mdx new file mode 100644 index 0000000..c5f5436 --- /dev/null +++ b/app/plant/bassia/page.mdx @@ -0,0 +1,23 @@ +# Kochia + +## _Bassia scoparia_ + +Kochia (sometimes incorrectly called "ragweed") is our less famous tumbleweed relative. This common weed is secret summer delicacy when cooked, with a flavor compared to grape leaves, olive oil, or nori. + +Kochia **needs to be thoroughly cooked** to be palatable and safe to eat. I usually boil it for a few minutes or fry it for a while (at least 10 minutes). When cooked, it changes color and will become soft if boiled. + +Plants can be fibrous. To harvest the leaves, be gentle. If a stem breaks off easily, it will be soft and good eating. If you pull too hard, you'll break of stems. + +Alternatively, break up the fiber by running it through a blender after boiling. This makes for a delicious saag paneer, or use it any way you'd use blended spinach. + +Kochia is widespread and easy to find. It grows in the bosque, gardens, empty lots and alleyways. It prefers disturbed soil and is often found growing with [tumbleweeds](salsola) and goatheads and seasonally swapping places with [samara ratha](sisybrium). + +Kochia is easily confused with our native purple aster (Dieteria canescens), especially when small. Look closely at leaf margins to differentiate them. Kochia leaves are also slightly fuzzy. + +![Kochia flowers](/assets/bassia/img/flowers.jpg "Those tiny flowers along kochia stems release wind-borne pollen, ensuring the plant's genetic diversity. Unfortunately, some human immune systems don't appreciate it!") + +In its native China and Japan, its cultivated for food and as an ornamental, and seeds are also eaten. Kochia was introduced to the US as an ornamental around 1900. Unfortunately, its food use isn''t widely known in the US, where it's usually regarded as a useless weed, or animal fodder at best. + +Leaves are very high in protein. Chickens love it raw. + +C4 photosynthesis. diff --git a/app/plant/chenopodium/page.mdx b/app/plant/chenopodium/page.mdx new file mode 100644 index 0000000..20c79a0 --- /dev/null +++ b/app/plant/chenopodium/page.mdx @@ -0,0 +1,13 @@ +# Quelites + +### _Chenopodium album_ + +Quelites (Spanish, pronounced “keh-LEE-tays”) or lambsquarters is a common garden weed with a long history of use in New Mexico. + +Leaves can be eaten raw but large quantities are better cooked. Use it how you use spinach: fried with onions and garlic is a popular. + +In Mexico, the term "quelites" refers to a any wild green, including [amaranth](amaranthus) and [verdolagas](portulaca). But here in New Mexico, it's specific to chenopodiums. Across the rest of the USA, this plant is most commonly called lambsquarters, and it's found almost everywhere in the world. + +We also have several native species in the area, but the non-native _Chenopodium album_ is by far the most ubiquitous. + +One of these wild species, _C. berlandieri_, is an ancient food throughout the Americas, independently domesticated by 4000 BC in Eastern North America as well as in Mexico as _huauzontle_, an important Aztec crop that is still grown today. Quinoa likely originated from the same wild species in the Andes. diff --git a/app/plant/layout.js b/app/plant/layout.js new file mode 100644 index 0000000..f9e97d3 --- /dev/null +++ b/app/plant/layout.js @@ -0,0 +1,3 @@ +export default function PlantProfile({ children }) { + return
{children}
; +} diff --git a/app/plant/morus/page.mdx b/app/plant/morus/page.mdx new file mode 100644 index 0000000..7f76ee7 --- /dev/null +++ b/app/plant/morus/page.mdx @@ -0,0 +1,3 @@ +# Mulberry + +## _Morus alba_ diff --git a/app/plant/portulaca/page.mdx b/app/plant/portulaca/page.mdx new file mode 100644 index 0000000..2ff2e3a --- /dev/null +++ b/app/plant/portulaca/page.mdx @@ -0,0 +1,17 @@ +# Verdolagas + +### _Portulaca oleracea_ + +Verdolagas or purslane is an ephemeral succulent that grows with the monsoon rains. It's highly regarded in traditional New Mexican cooking and a component of indigenous diets throughout the world, as it grows almost everywhere! + +Its flavor changes throughout the day: it tastes tart and fresh when picked in the morning. + +It's delicious raw on sandwiches or in salads. It's also excellent stir-fried, or it can thicken soups with its mucilaginous quality! Slime-haters fear not, it's not as slimy as okra or nopales. + +Don't mix it up with spurge! That's a similar looking plant that is mildly toxic. Spurge leaves are smaller and less succulent, and the plant leaks a milky sap. + +Also, don't confuse it with the broader leaves of the similar-looking but unrelated horsepurslane (Trianthema portulacastrum). Horsepurslane is technically edible but unpleasant. + +Purslane is found almost everywhere in the world, and predates Columbus in the Americas. + +C4 + CAM photosysnthesis, switches depending on water availability. diff --git a/public/assets/prunus/about.md b/app/plant/prunus/page.mdx similarity index 94% rename from public/assets/prunus/about.md rename to app/plant/prunus/page.mdx index 2f23b35..7a30416 100644 --- a/public/assets/prunus/about.md +++ b/app/plant/prunus/page.mdx @@ -1,3 +1,7 @@ +# Cherry Plum + +### _Prunus cerasifera_ + The purple cherry plum is a popular ornamental tree in Albuquerque. Many people don't realize that the plums produced are perfectly edible and delicious. If you like tart flavors, they're great fresh off the tree! For a sweeter treat, process them as you would cherries. After pitting with a cherry pitter, they make an incredible pie filling. diff --git a/app/plant/salsola/page.mdx b/app/plant/salsola/page.mdx new file mode 100644 index 0000000..b179163 --- /dev/null +++ b/app/plant/salsola/page.mdx @@ -0,0 +1,7 @@ +# Tumbleweed + +### _Salsola tragus_ + +The famous tumbleweed or Russian Thistle (Salsola tragus) is edible before it becomes prickly. + +It was accidentally introduced in the 1870s and soon rolled its way across the west. Tumbleweeds are extremely genetically diverse, and there may be 4 or more species and hybrids in the US. diff --git a/app/plant/sisybrium/page.mdx b/app/plant/sisybrium/page.mdx new file mode 100644 index 0000000..d36d9a0 --- /dev/null +++ b/app/plant/sisybrium/page.mdx @@ -0,0 +1,17 @@ +# Samara Ratha + +## _Sisymbrium irio_ + +Samara ratha (Arabic: سمارة رثة), London rocket, or wild arugula is an abundant mustard and winter weed in the city. + +These leaves pack a wasabi-like bite. To some, it's an acquired taste, best used in moderation as an herb. Others, like me, love the spicy flavor and enjoy it as a salad green. + +Grows in disturbed, sandy areas. Plants tent to grow larger and taste better in areas that receive some shade. Look on the north sides of walls. + +During dryer winters, samara ratha is found mostly in places that collect runoff or receive irrigation. Following heavy rain and snow, it grows ubiquitously. + +Samara ratha can be confused with sow thistle (Sonchus sp.) or prickly lettuce (Lactuca serriola), which can have similar leaf shapes. Both are edible but very bitter. Both leak a white sap when cut, which samara ratha does not. + +![Chickens eating samara ratha](/assets/sisybrium/img/chickens.jpg "Chicks dig samara ratha") + +Use as basil in pesto for a spicy twist. diff --git a/app/plant/ulmus/page.mdx b/app/plant/ulmus/page.mdx new file mode 100644 index 0000000..6f151c8 --- /dev/null +++ b/app/plant/ulmus/page.mdx @@ -0,0 +1,13 @@ +# Siberian Elm + +## _Ulmus pumila_ + +Look out a window in Albuquerque or another Southwest town, and there's a good chance you'll see a Siberian elm. Introduced to fight the dust bowl, these are a common shade tree and have escaped into wild habitats like our bosque. In early spring, they produce an abundance of bright green seed pods that are easily mistaken for leaves, called "samaras." They are edible and palatable with a mild, fresh leafy taste. + +To harvest, simply strip the seeds from the branches. Don't worry if you get some leaves and flowers, they're edible too! + +![image](/assets/ulmus/img/handful.jpg "A handful of elm samaras. The small brown things are flowers.") + +Pop them into your mouth for a fresh greens snack on a walk! But they really shine added to a salad, or even as the main component! If you like a spicier salad, throw in a bit of [samara ratha](sisybrium) to add a kick! + +The Siberian elm may be confused with the lacebark elm, as both species are sometimes known as "chinese elm." Lacebark elms can be found as street trees in Albuquerque and lack their cousin's invasive habit. Their samaras are also edible. diff --git a/src/components/ResponsibleForaging/ResponsibleForaging.scss b/app/responsible-foraging/ResponsibleForaging.scss similarity index 81% rename from src/components/ResponsibleForaging/ResponsibleForaging.scss rename to app/responsible-foraging/ResponsibleForaging.scss index a378cf9..a92f059 100644 --- a/src/components/ResponsibleForaging/ResponsibleForaging.scss +++ b/app/responsible-foraging/ResponsibleForaging.scss @@ -1,4 +1,4 @@ -@import "../../styles/variables"; +@import "styles/variables"; .textBox { margin: 2em; diff --git a/src/components/ResponsibleForaging/ResponsibleForaging.js b/app/responsible-foraging/page.js similarity index 87% rename from src/components/ResponsibleForaging/ResponsibleForaging.js rename to app/responsible-foraging/page.js index 183d128..b4b88c3 100644 --- a/src/components/ResponsibleForaging/ResponsibleForaging.js +++ b/app/responsible-foraging/page.js @@ -1,3 +1,5 @@ +"use client"; + import React, { useState, useEffect } from "react"; import ReactMarkdown from "react-markdown"; import "./ResponsibleForaging.scss"; @@ -13,7 +15,7 @@ const ResponsibleForaging = () => { return (
- + {markdownContent}
); }; diff --git a/components/Footer/Footer.scss b/components/Footer/Footer.scss new file mode 100644 index 0000000..0cd3531 --- /dev/null +++ b/components/Footer/Footer.scss @@ -0,0 +1,8 @@ +@import "styles/variables"; + +.footer { + background-color: $theme-color; + color: $text-color; + padding: 10px; + text-align: center; +} diff --git a/src/components/Footer/index.js b/components/Footer/index.js similarity index 74% rename from src/components/Footer/index.js rename to components/Footer/index.js index fd5a472..785b63a 100644 --- a/src/components/Footer/index.js +++ b/components/Footer/index.js @@ -1,13 +1,13 @@ import React from "react"; import "./Footer.scss"; -import { NavLink } from "react-router-dom"; +import Link from "next/link"; const Footer = () => { return (