diff --git a/.gitignore b/.gitignore index 6375d91..1f26463 100644 --- a/.gitignore +++ b/.gitignore @@ -4,4 +4,7 @@ .DS_Store _dl/ docs/_site/ - +node_modules +docs/.vite +dist +.env diff --git a/LICENSE b/LICENSE deleted file mode 100644 index 07a6d17..0000000 --- a/LICENSE +++ /dev/null @@ -1,22 +0,0 @@ - -The MIT License (MIT) - -Copyright (c) 2013-2016 Blackrock Digital LLC. - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. \ No newline at end of file diff --git a/Makefile b/Makefile deleted file mode 100644 index 7ab27d7..0000000 --- a/Makefile +++ /dev/null @@ -1,39 +0,0 @@ -BOOTSTRAP_VERSION=5.2.3 - -BOOTSTRAP_URL=https://github.com/twbs/bootstrap/releases/download/v${BOOTSTRAP_VERSION}/bootstrap-${BOOTSTRAP_VERSION}-dist.zip -DEPENDS= \ - docs/js/bootstrap.bundle.min.js \ - docs/js/bootstrap.bundle.min.js.map \ - docs/css/bootstrap.min.css \ - docs/css/bootstrap.min.css.map - -# Update dependencies, build container and start local web site -all: fetch - ${MAKE} up -up: - docker compose up --build - -build: fetch - docker compose build - -fetch: ${DEPENDS} - -docs/js/bootstrap.bundle.min.js docs/js/bootstrap.bundle.min.js.map: _dl/bootstrap-${BOOTSTRAP_VERSION}-dist.zip - cp -p _dl/bootstrap-${BOOTSTRAP_VERSION}-dist/js/bootstrap.bundle.min.js docs/js/bootstrap.bundle.min.js - cp -p _dl/bootstrap-${BOOTSTRAP_VERSION}-dist/js/bootstrap.bundle.min.js.map docs/js/bootstrap.bundle.min.js.map - -docs/css/bootstrap.min.css docs/css/bootstrap.min.css.map: _dl/bootstrap-${BOOTSTRAP_VERSION}-dist.zip - cp -p _dl/bootstrap-${BOOTSTRAP_VERSION}-dist/css/bootstrap.min.css docs/css/bootstrap.min.css - cp -p _dl/bootstrap-${BOOTSTRAP_VERSION}-dist/css/bootstrap.min.css.map docs/css/bootstrap.min.css.map - -_dl/bootstrap-${BOOTSTRAP_VERSION}-dist.zip: _dl - cd _dl && umask 0 && \ - wget -N -q ${BOOTSTRAP_URL} && \ - unzip -q -o bootstrap-${BOOTSTRAP_VERSION}-dist.zip -_dl: - mkdir _dl -clean: - -rm -rf docs/_site _dl - -rm -f ${DEPENDS} - -true: ; diff --git a/README.md b/README.md index 62af89d..29d4d4b 100644 --- a/README.md +++ b/README.md @@ -1,80 +1,24 @@ -# things-nyc-www +# The Things — NYC (React + Vite + Tailwind) -Website for The Things Network New York. +A modern, static website for **The Things Network New York** built with **React (Vite)** and **Tailwind CSS**. -Changes made here will be reflected on [`thethings.nyc`](https://thethings.nyc) upon being reviewed & pulled by the webmaster. +## Tech Stack -## Development +- **React 18** (via Vite) — fast dev server and HMR +- **TypeScript** — safer, self-documenting code +- **Tailwind CSS** — utility-first styling, tiny final CSS -The site is static HTML generated from markdown with -[jekyll](https://jekyllrb.com/), using the [Bootstrap -5](https://getbootstrap.com/docs/5.2/getting-started/introduction/) framework. +## Getting Started -Website pages live in the `docs` directory. +### Prerequisites -### Updating the web pages +- Node.js 18+ (`node -v`) +- npm (`npm -v`) -XXX - Add some notes about the layout of the directory and what to -modify. - -XXX - Add notes on how to add a blog entry. - -### Running under docker - -#### TL;DR +### 1) Install & Run ```bash -git clone https://github.com/things-nyc/things-nyc.github.io.git -cd things-nyc.github.io -make -# Open http://localhost:4000 in your browser -# Edit files in docs/ -# Commit your changes and push to a branch -# Create a Pull Request on Github +npm install +npm run dev +# open http://localhost:5173 ``` - -#### Notes - -The `_dl` and `_site` directories are temporary, created by the fetch -and build process, any changes there will be overwritten. -Use -```bash -make clean -``` -to delete them. -They will not saved to github. - -To update a JavaScript package, update the version info in the -`Makefile` and -```bash -make clean fetch -``` - -#### Details - -If you don't want to install Ruby and Jekyll (hint: you don't) you can use the Docker container. -Install [Docker](https://www.docker.com/community-edition#/download) and [Docker-compose](https://docs.docker.com/compose/install/#install-compose). -Clone the repo. -Run `docker-compose up` from any project directory to start the container. -The project directory is mounted as a volume in the container so you can edit the files with your normal editor. -Jekyll will automatically generate new HTML when you make changes. -The container runs a web server [http://0.0.0.0:4000](http://0.0.0.0:4000) so you can preview your work. - -### Docker Troubleshooting - -During the build, you may get DNS failures similar to: - -```console -Err:1 http://security.debian.org/debian-security buster/updates InRelease - Temporary failure resolving 'security.debian.org' -``` - -In that case, follow the suggestions from [StackOverflow](https://stackoverflow.com/questions/61567404/docker-temporary-failure-resolving-deb-debian-org): - -* Try `sudo service docker restart`, then retry `docker-compose build`. -* If appropriate, try `sudo /etc/init.d/docker restart`, then retry `docker-compose build` -* Try rebooting the Linux system, then retry `docker-compose build`. - -In our limited experience, the first step was enough. - - diff --git a/README_Bootstrap.md b/README_Bootstrap.md deleted file mode 100644 index 1271b84..0000000 --- a/README_Bootstrap.md +++ /dev/null @@ -1,27 +0,0 @@ -# [Start Bootstrap](http://startbootstrap.com/) - [Stylish Portfolio](http://startbootstrap.com/template-overviews/stylish-portfolio/) - -[Stylish Portfolio](http://startbootstrap.com/template-overviews/stylish-portfolio/) is a responsive, one page portfolio theme for [Bootstrap](http://getbootstrap.com/) created by [Start Bootstrap](http://startbootstrap.com/). The theme features multiple content sections with an off canvas navigation menu. - -## Getting Started - -To begin using this template, choose one of the following options to get started: -* [Download the latest release on Start Bootstrap](http://startbootstrap.com/template-overviews/stylish-portfolio/) -* Clone the repo: `git clone https://github.com/BlackrockDigital/startbootstrap-stylish-portfolio.git` -* Fork the repo - -## Bugs and Issues - -Have a bug or an issue with this template? [Open a new issue](https://github.com/BlackrockDigital/startbootstrap-stylish-portfolio/issues) here on GitHub or leave a comment on the [template overview page at Start Bootstrap](http://startbootstrap.com/template-overviews/stylish-portfolio/). - -## Creator - -Start Bootstrap was created by and is maintained by **[David Miller](http://davidmiller.io/)**, Owner of [Blackrock Digital](http://blackrockdigital.io/). - -* https://twitter.com/davidmillerskt -* https://github.com/davidtmiller - -Start Bootstrap is based on the [Bootstrap](http://getbootstrap.com/) framework created by [Mark Otto](https://twitter.com/mdo) and [Jacob Thorton](https://twitter.com/fat). - -## Copyright and License - -Copyright 2013-2016 Blackrock Digital LLC. Code released under the [MIT](https://github.com/BlackrockDigital/startbootstrap-stylish-portfolio/blob/gh-pages/LICENSE) license. diff --git a/build/Dockerfile b/build/Dockerfile deleted file mode 100644 index 6309613..0000000 --- a/build/Dockerfile +++ /dev/null @@ -1,24 +0,0 @@ -FROM ruby:2.7.3-alpine - -ENV \ - LANG=en_US.UTF-8 \ - LANGUAGE=en_US.UTF-8 \ - LC_ALL=en_US.UTF-8 - -COPY Gemfile Gemfile.lock /src/gh/pages-gem/ - -# one step to exclude .build_deps from docker cache -RUN \ - echo "*** Install build dependencies ***" && \ - apk update && apk add --no-cache git && \ - echo "*** Install required packages ***" && \ - apk add --no-cache --virtual .build_deps make build-base && \ - echo "*** Build jekyl ***" && \ - bundle config local.github-pages /src/gh/pages-gem && \ - bundle install --gemfile=/src/gh/pages-gem/Gemfile && \ - echo "*** Clean up build dependencies ***" && \ - apk del .build_deps - -WORKDIR /src/site - -CMD ["jekyll", "serve", "-H", "0.0.0.0", "-P", "4000"] diff --git a/build/Gemfile b/build/Gemfile deleted file mode 100644 index b0ba5aa..0000000 --- a/build/Gemfile +++ /dev/null @@ -1,3 +0,0 @@ -source "https://rubygems.org" - -gem "github-pages", group: :jekyll_plugins \ No newline at end of file diff --git a/build/Gemfile.lock b/build/Gemfile.lock deleted file mode 100644 index 180006e..0000000 --- a/build/Gemfile.lock +++ /dev/null @@ -1,272 +0,0 @@ -GEM - remote: https://rubygems.org/ - specs: - activesupport (7.1.2) - base64 - bigdecimal - concurrent-ruby (~> 1.0, >= 1.0.2) - connection_pool (>= 2.2.5) - drb - i18n (>= 1.6, < 2) - minitest (>= 5.1) - mutex_m - tzinfo (~> 2.0) - addressable (2.8.6) - public_suffix (>= 2.0.2, < 6.0) - base64 (0.2.0) - bigdecimal (3.1.5) - coffee-script (2.4.1) - coffee-script-source - execjs - coffee-script-source (1.11.1) - colorator (1.1.0) - commonmarker (0.23.10) - concurrent-ruby (1.2.2) - connection_pool (2.4.1) - dnsruby (1.70.0) - simpleidn (~> 0.2.1) - drb (2.2.0) - ruby2_keywords - em-websocket (0.5.3) - eventmachine (>= 0.12.9) - http_parser.rb (~> 0) - ethon (0.16.0) - ffi (>= 1.15.0) - eventmachine (1.2.7) - execjs (2.9.1) - faraday (2.7.12) - base64 - faraday-net_http (>= 2.0, < 3.1) - ruby2_keywords (>= 0.0.4) - faraday-net_http (3.0.2) - ffi (1.16.3) - forwardable-extended (2.6.0) - gemoji (3.0.1) - github-pages (228) - github-pages-health-check (= 1.17.9) - jekyll (= 3.9.3) - jekyll-avatar (= 0.7.0) - jekyll-coffeescript (= 1.1.1) - jekyll-commonmark-ghpages (= 0.4.0) - jekyll-default-layout (= 0.1.4) - jekyll-feed (= 0.15.1) - jekyll-gist (= 1.5.0) - jekyll-github-metadata (= 2.13.0) - jekyll-include-cache (= 0.2.1) - jekyll-mentions (= 1.6.0) - jekyll-optional-front-matter (= 0.3.2) - jekyll-paginate (= 1.1.0) - jekyll-readme-index (= 0.3.0) - jekyll-redirect-from (= 0.16.0) - jekyll-relative-links (= 0.6.1) - jekyll-remote-theme (= 0.4.3) - jekyll-sass-converter (= 1.5.2) - jekyll-seo-tag (= 2.8.0) - jekyll-sitemap (= 1.4.0) - jekyll-swiss (= 1.0.0) - jekyll-theme-architect (= 0.2.0) - jekyll-theme-cayman (= 0.2.0) - jekyll-theme-dinky (= 0.2.0) - jekyll-theme-hacker (= 0.2.0) - jekyll-theme-leap-day (= 0.2.0) - jekyll-theme-merlot (= 0.2.0) - jekyll-theme-midnight (= 0.2.0) - jekyll-theme-minimal (= 0.2.0) - jekyll-theme-modernist (= 0.2.0) - jekyll-theme-primer (= 0.6.0) - jekyll-theme-slate (= 0.2.0) - jekyll-theme-tactile (= 0.2.0) - jekyll-theme-time-machine (= 0.2.0) - jekyll-titles-from-headings (= 0.5.3) - jemoji (= 0.12.0) - kramdown (= 2.3.2) - kramdown-parser-gfm (= 1.1.0) - liquid (= 4.0.4) - mercenary (~> 0.3) - minima (= 2.5.1) - nokogiri (>= 1.13.6, < 2.0) - rouge (= 3.26.0) - terminal-table (~> 1.4) - github-pages-health-check (1.17.9) - addressable (~> 2.3) - dnsruby (~> 1.60) - octokit (~> 4.0) - public_suffix (>= 3.0, < 5.0) - typhoeus (~> 1.3) - html-pipeline (2.14.3) - activesupport (>= 2) - nokogiri (>= 1.4) - http_parser.rb (0.8.0) - i18n (1.14.1) - concurrent-ruby (~> 1.0) - jekyll (3.9.3) - addressable (~> 2.4) - colorator (~> 1.0) - em-websocket (~> 0.5) - i18n (>= 0.7, < 2) - jekyll-sass-converter (~> 1.0) - jekyll-watch (~> 2.0) - kramdown (>= 1.17, < 3) - liquid (~> 4.0) - mercenary (~> 0.3.3) - pathutil (~> 0.9) - rouge (>= 1.7, < 4) - safe_yaml (~> 1.0) - jekyll-avatar (0.7.0) - jekyll (>= 3.0, < 5.0) - jekyll-coffeescript (1.1.1) - coffee-script (~> 2.2) - coffee-script-source (~> 1.11.1) - jekyll-commonmark (1.4.0) - commonmarker (~> 0.22) - jekyll-commonmark-ghpages (0.4.0) - commonmarker (~> 0.23.7) - jekyll (~> 3.9.0) - jekyll-commonmark (~> 1.4.0) - rouge (>= 2.0, < 5.0) - jekyll-default-layout (0.1.4) - jekyll (~> 3.0) - jekyll-feed (0.15.1) - jekyll (>= 3.7, < 5.0) - jekyll-gist (1.5.0) - octokit (~> 4.2) - jekyll-github-metadata (2.13.0) - jekyll (>= 3.4, < 5.0) - octokit (~> 4.0, != 4.4.0) - jekyll-include-cache (0.2.1) - jekyll (>= 3.7, < 5.0) - jekyll-mentions (1.6.0) - html-pipeline (~> 2.3) - jekyll (>= 3.7, < 5.0) - jekyll-optional-front-matter (0.3.2) - jekyll (>= 3.0, < 5.0) - jekyll-paginate (1.1.0) - jekyll-readme-index (0.3.0) - jekyll (>= 3.0, < 5.0) - jekyll-redirect-from (0.16.0) - jekyll (>= 3.3, < 5.0) - jekyll-relative-links (0.6.1) - jekyll (>= 3.3, < 5.0) - jekyll-remote-theme (0.4.3) - addressable (~> 2.0) - jekyll (>= 3.5, < 5.0) - jekyll-sass-converter (>= 1.0, <= 3.0.0, != 2.0.0) - rubyzip (>= 1.3.0, < 3.0) - jekyll-sass-converter (1.5.2) - sass (~> 3.4) - jekyll-seo-tag (2.8.0) - jekyll (>= 3.8, < 5.0) - jekyll-sitemap (1.4.0) - jekyll (>= 3.7, < 5.0) - jekyll-swiss (1.0.0) - jekyll-theme-architect (0.2.0) - jekyll (> 3.5, < 5.0) - jekyll-seo-tag (~> 2.0) - jekyll-theme-cayman (0.2.0) - jekyll (> 3.5, < 5.0) - jekyll-seo-tag (~> 2.0) - jekyll-theme-dinky (0.2.0) - jekyll (> 3.5, < 5.0) - jekyll-seo-tag (~> 2.0) - jekyll-theme-hacker (0.2.0) - jekyll (> 3.5, < 5.0) - jekyll-seo-tag (~> 2.0) - jekyll-theme-leap-day (0.2.0) - jekyll (> 3.5, < 5.0) - jekyll-seo-tag (~> 2.0) - jekyll-theme-merlot (0.2.0) - jekyll (> 3.5, < 5.0) - jekyll-seo-tag (~> 2.0) - jekyll-theme-midnight (0.2.0) - jekyll (> 3.5, < 5.0) - jekyll-seo-tag (~> 2.0) - jekyll-theme-minimal (0.2.0) - jekyll (> 3.5, < 5.0) - jekyll-seo-tag (~> 2.0) - jekyll-theme-modernist (0.2.0) - jekyll (> 3.5, < 5.0) - jekyll-seo-tag (~> 2.0) - jekyll-theme-primer (0.6.0) - jekyll (> 3.5, < 5.0) - jekyll-github-metadata (~> 2.9) - jekyll-seo-tag (~> 2.0) - jekyll-theme-slate (0.2.0) - jekyll (> 3.5, < 5.0) - jekyll-seo-tag (~> 2.0) - jekyll-theme-tactile (0.2.0) - jekyll (> 3.5, < 5.0) - jekyll-seo-tag (~> 2.0) - jekyll-theme-time-machine (0.2.0) - jekyll (> 3.5, < 5.0) - jekyll-seo-tag (~> 2.0) - jekyll-titles-from-headings (0.5.3) - jekyll (>= 3.3, < 5.0) - jekyll-watch (2.2.1) - listen (~> 3.0) - jemoji (0.12.0) - gemoji (~> 3.0) - html-pipeline (~> 2.2) - jekyll (>= 3.0, < 5.0) - kramdown (2.3.2) - rexml - kramdown-parser-gfm (1.1.0) - kramdown (~> 2.0) - liquid (4.0.4) - listen (3.8.0) - rb-fsevent (~> 0.10, >= 0.10.3) - rb-inotify (~> 0.9, >= 0.9.10) - mercenary (0.3.6) - mini_portile2 (2.8.5) - minima (2.5.1) - jekyll (>= 3.5, < 5.0) - jekyll-feed (~> 0.9) - jekyll-seo-tag (~> 2.1) - minitest (5.20.0) - mutex_m (0.2.0) - nokogiri (1.15.5) - mini_portile2 (~> 2.8.2) - racc (~> 1.4) - octokit (4.25.1) - faraday (>= 1, < 3) - sawyer (~> 0.9) - pathutil (0.16.2) - forwardable-extended (~> 2.6) - public_suffix (4.0.7) - racc (1.7.3) - rb-fsevent (0.11.2) - rb-inotify (0.10.1) - ffi (~> 1.0) - rexml (3.2.6) - rouge (3.26.0) - ruby2_keywords (0.0.5) - rubyzip (2.3.2) - safe_yaml (1.0.5) - sass (3.7.4) - sass-listen (~> 4.0.0) - sass-listen (4.0.0) - rb-fsevent (~> 0.9, >= 0.9.4) - rb-inotify (~> 0.9, >= 0.9.7) - sawyer (0.9.2) - addressable (>= 2.3.5) - faraday (>= 0.17.3, < 3) - simpleidn (0.2.1) - unf (~> 0.1.4) - terminal-table (1.8.0) - unicode-display_width (~> 1.1, >= 1.1.1) - typhoeus (1.4.1) - ethon (>= 0.9.0) - tzinfo (2.0.6) - concurrent-ruby (~> 1.0) - unf (0.1.4) - unf_ext - unf_ext (0.0.9.1) - unicode-display_width (1.8.0) - -PLATFORMS - ruby - -DEPENDENCIES - github-pages - -BUNDLED WITH - 2.1.4 diff --git a/docker-compose.yml b/docker-compose.yml deleted file mode 100644 index 6a82467..0000000 --- a/docker-compose.yml +++ /dev/null @@ -1,12 +0,0 @@ ---- -version: "3.2" - -services: - web: - build: build - volumes: - - ./docs:/src/site - ports: - - "4000:4000" - container_name: things-nyc-web -... diff --git a/docs/CNAME b/docs/CNAME deleted file mode 100644 index 22cfcc7..0000000 --- a/docs/CNAME +++ /dev/null @@ -1 +0,0 @@ -thethings.nyc \ No newline at end of file diff --git a/docs/_config.yml b/docs/_config.yml deleted file mode 100644 index efc9c9b..0000000 --- a/docs/_config.yml +++ /dev/null @@ -1,18 +0,0 @@ ---- -timezone: America/New_York -# source: source_folder -collections: - posts: - output: true - stories: - output: true -#remote_theme: BlackrockDigital/startbootstrap-stylish-portfolio -repository: things-nyc/things-nyc.github.io -permalink: pretty -defaults: - - - scope: - path: "" # an empty string here means all files in the project - values: - layout: "default" -... diff --git a/docs/_data/faq.yml b/docs/_data/faq.yml deleted file mode 100644 index 0d4d362..0000000 --- a/docs/_data/faq.yml +++ /dev/null @@ -1,105 +0,0 @@ ---- -- section: General - questions: - - question: >- - What is The Things Network and how is it different from - LoRaWAN and LoRa? - answer: >- - The Things Network (TTN) is a free data network for the - Internet of Things. LoRa is an innovative way of using - unlicensed radio spectrum to transmit small amounts of data, - at long range with minimal power. The Things Network uses a - standardized protocol called LoRaWAN which uses LoRa - technology to connect many devices to the Internet. - - question: What is the difference between a node and a gateway? - answer: >- - Nodes are usually small, battery-powered sensors that upload - their data to the Internet via The Things Network. Gateways - are strategically-placed access points that provide coverage - for The Things Network. - - question: >- - What is the difference between network operators, application - providers, and application users? - answer: >- - Network operators are the many community members (both - corporate and individual) who own and operate the - infrastructure behind The Things Network. Application - providers provide services based on data and analytics from - nodes they control. The application users benefit from the - data from applications. - - question: >- - Does The Things Network New York provide a Service Level - Agreement (SLA)? - answer: >- - No, but application providers may. - - Let's take an example. Suppose a company called "TrashAware" - provides a garbage can monitoring service to U.S. cities. The - city of "Smallville" is interested in TrashAware's product but - requires an SLA stipulating 99.9% uptime. TrashAware assesses - the current network coverage in Smallville, and then partners - with the city to deploy additional gateways to ensure complete - coverage and reliable service. TrashAware then issues an SLA - to Smallville covering their entire application, which - includes availability of data via their website and a mobile - application. -- section: Security and Privacy - questions: - - question: >- - As a gateway operator, does installing the gateway make my own - network vulnerable? - answer: >- - Technically yes, but the security risk is less than a - smartphone connecting to your network's WiFi. - - A gateway _does_ technically represent an additional - access point into a LAN and should not be placed inside of - a trusted zone, however it is an order of magnitude less - risk than a smartphone or employee PC. The gateways use - industry-standard access control and are secured with - administrative credentials setup during - installation. While vulnerabilities via the packet - forwarding protocol or the LoRa interface are conceivable, - they are highly unlikely in practice. A LAN operator can - mitigate the risk of compromised gateways on their network - by placing them in a separate segment (VLAN), as is - routinely done in corporate networks. - - question: As an application provider or user, is my data private? - answer: >- - Data is encrypted from the node to the application: The - Things Network does not have access to the decrypted data. - - It is the application provider's responsibility to ensure - that their nodes are designed to adequately protect data - prior to transmission. LoRaWAN has AES128 encryption by - default, which should be sufficient for most uses, and - additional encryption and security measures can be applied - for applications which require them. - - The greatest threat to privacy is not in The Things - Network itself, but rather in the third-party applications - where the data is stored. TTN has no control over the - security of data after it has been sent to and decrypted - by applications. A bad actor could theoretically break - into the application server and steal/delete/manipulate - data or send control commands to IoT devices. Thus, - application providers must take security precautions to - ensure users can trust them with their data. This is a - challenge for IoT in general and not specific to TTN. - - At the end of the day, if you are using any wireless tech - whatsoever, you are transmitting in spectrum that is - easily monitored by the public, so you must secure the - data at the transmitter and not trust the network like we - could(?) with landline telephone. That said, of course we - should encourage good security/privacy practices - throughout the network. - - question: >- - As an operator of a gateway, am I responsible for user's - privacy? - answer: >- - No. The gateways simply listen for radio signals from - nodes and pass encrypted data to the network. Gateways do - not contain decryption keys or any privileged information - about users. -... diff --git a/docs/_data/links.yml b/docs/_data/links.yml deleted file mode 100644 index b6a16a3..0000000 --- a/docs/_data/links.yml +++ /dev/null @@ -1,30 +0,0 @@ ---- -- url: https://eepurl.com/ccBERT - title: Mailing List - -- url: https://www.meetup.com/The-Things-Network-NYC-Community-Meetup/ - title: Meetup - -- url: https://things-nyc.slack.com/ - title: Slack - -- url: https://github.com/things-nyc - title: Github - -- url: https://masto.nyc/@thethingsnyc - title: Follow us on Mastodon - -- url: https://thethingsnetwork.org/ - title: The Things Network Global Website - -# - url: https://thethingsnetwork.org/wiki/ -# title: TheThingsNetwork Global Wiki -# disabled: true - -- url: https://forum.thethingsnetwork.org/ - title: The Things Network Global Forum - -- url: https://the-things-network-new-york-inc.square.site/ - title: Donate (tax deductable) - -... diff --git a/docs/_data/people.yml b/docs/_data/people.yml deleted file mode 100644 index 80adb33..0000000 --- a/docs/_data/people.yml +++ /dev/null @@ -1,44 +0,0 @@ ---- -# Specific people named in site with profile link. -# KEEP THIS SORTED BY LAST NAME - -forrestfiller: - name: Forrest Filler - profile: https://github.com/forrestfiller - -mimiflynn: - name: Mimi Flynn - profile: https://github.com/mimiflynn - -elliotthighfill: - name: Elliott Highfill - profile: https://github.com/highfile - -jeffhonig: - name: Jeff Honig - profile: https://github.com/jchonig - -chrismerck: - name: Chris Merck - profile: https://github.com/chrismerck - -terrymoore: - name: Terry Moore - profile: https://github.com/terrillmoore - -frankleonrose: - name: Frank Leon Rose - profile: https://github.com/frankleonrose - -chrisstratton: - name: Chris Stratton - profile: https://github.com/cstratton - -brianvanthull: - name: Brian Vant-Hull - -jonbosak: - name: Jon Bosak - profile: https://en.wikipedia.org/wiki/Jon_Bosak - -... diff --git a/docs/_data/projects.yml b/docs/_data/projects.yml deleted file mode 100644 index 04bedfb..0000000 --- a/docs/_data/projects.yml +++ /dev/null @@ -1,157 +0,0 @@ ---- -- Title: Outreach and Gateway Deployment - Lead: terrymoore - Type: Organization - Description: | - The fundamental purpose of the organization is to build a network of technical experts to support students, teachers, researchers, experimenters and entrepreneurs in using remote sensing technology to advance our knowledge about and managament of physical processes in New York and around the world. Both to help build our own skills, and to help our users, we're deploying the free-to-use Things Network throughout New York City. - A key part of that effort is spreading the word about - The Things Network and the benefits of joining an open IoT network. - - Outreach includes participating in hackathon and workshop events, presenting in various technology fora, - and meeting with commercial, non-profit, and government organizations that might benefit from using - TTN. In addition, the group recommends hardware, software and cloud solutions, and offer direct on-site support to people who want to deploy devices or a gateway. - Status: Ongoing - Nextsteps: - - More in-person hands-on make-it-work workshops. - - Deploy fixed rooftop gateway with large antenna in commercial building. - - Fundraising to deploy a dense network of gateways - -- Title: Gateway fleet management system - Lead: jeffhonig - Contributors: terrymoore - Type: System - Description: | - A system supporting the deployment, monitoring, and maintenance of a fleet of Multi-Tech - Conduit and Conduit AP gateways. As part of deploying hundreds of gateways to cover - NYC and Ithaca regions of New York State, the group manages these - gateways as a service to gateway owners. The system uses the Ansible Configuration - Management tool to drive gateway configuration, an SSH jumphost to enable secure remote - access. - Status: Active Development, being used to deploy and monitor gateways - Nextsteps: - - Improve robustness - - Continuous integration testing - Documentation: https://github.com/IthacaThings/ttn-multitech-cm - Repositories: - - https://github.com/IthacaThings/ttn-multitech-cm - - https://github.com/IthacaThings/meta-ttni - - https://github.com/jchonig/mlinux-be - - https://hub.docker.com/r/jchonig/mlinux-be - -- Title: Organization, Presence, and Funding - Lead: terrymoore - Contributors: - - forrestfiller - - mimiflynn - - frankleonrose - - elliotthighfill - Type: Organization - Description: | - TTN-NY as an organization needs legal structure, accounting, and governance. - It also needs to be present on the Web and social media in order to be found by people looking for - LoraWAN support in NYC. - We recently completed official registration as a 501(c)3, meaning that now we can accept tax deductable donations. - Status: Ongoing - Nextsteps: - - Add more project documentation on the website. - - Enable donations by engaging a fiscal sponsor. - - Meeting minutes and newsletter on website. - Repositories: - - https://github.com/things-nyc/things-nyc.github.io - - https://github.com/things-nyc/things-nyc-docs - - -- Title: Arduino LMIC Library - Lead: terrymoore - Contributors: frankleonrose - Type: Library - Description: | - The LMIC (LoRa-Mac in C) library came from IBM; the initial port to Arduino was done in Europe by Matthijs Kooijman, and is hosted here: - [https://github.com/matthijskooijman/arduino-lmic](https://github.com/matthijskooijman/arduino-lmic). - When the team at TTN-NY first started building Arduino nodes, they discovered many missing features related to - operating within the US band plan. Frank started the things-nyc repo; then Terry forked the things-nyc repo and made - even more extensive changes to support MCCI's Catena boards, including adding all global band plans and doing extensive testing and bug fixing. His repo - is now the offical home of Arduino LMIC for worldwide use. - Status: The TTN-NY repo is deprecated. The MCCI-Catena fork is our recommended building block for Arduino development with the 1276/8 chips (RFM-95). - Nextsteps: Add multicast and FUOTA support. - Repositories: - - https://github.com/mcci-catena/arduino-lmic - - https://github.com/things-nyc/arduino-lmic - - -- Title: Manhattan Mapper - Lead: frankleonrose - Contributors: - - mimiflynn - Type: Device - Description: | - Councilwoman Gale Brewer, Manhattan Borough President from 2014 to 2021, is a vocal advocate for building Smart City infrastructure - in an open way that encourages innovation. TTN-NY built a LoRa node with GPS to be installed - in Gale’s primary vehicle, so she could participate in the - development of a TTN coverage map as she conducts her business around the city. - Status: Proof of concept complete; project suspended. - Nextsteps: - - Write up build log - Repositories: - - https://github.com/frankleonrose/ManhattanMapper - - -- Title: HarlemHeat remote measurements - Lead: brianvanthull - Contributors: - - terrymoore - - frankleonrose - - forrestfiller - Type: Device - Description: | - As part of the Harlem Heat Project, Brian has deployed a number of off-the-shelf sensors to measure indoor - temperatures in the city. He would like to collect data from the sensors via TTN. However, he would like - to avoid having to visit the sensors to replace batteries every two weeks. - - Terry provided Brian with a set of [Catena](https://github.com/mcci-catena/HW-Designs)-based sensors as - a first stage of the project. They work well communicating with a gateway high on the CUNY campus, but they - still consume power at a higher rate than Brian would like. - - Frank and Forrest figured out the protocol for communicating with existing long-running off-the-shelf - temperature sensors. Now Frank is putting together a communications board that will be able to transmit - readings via LoRa while conserving power by going into deep sleep while inactive. - Status: Prototyping power management - Nextsteps: - - Deploy and test battery longevity - - -- Title: MapTheThings - Lead: frankleonrose - Contributors: forrestfiller - Type: - - Server - - Device - - App - Description: | - TTN Mapper [https://ttnmapper.org/](https://ttnmapper.org/) is the standard mapping service used by more than 1500 TTN users globally. - It contains more than 3 million transmission data points. - - Frank created the MapTheThings [https://map.thethings.nyc](https://map.thethings.nyc) service as a fully open source alternative - with scalability as a primary goal. The service summarizes successful and attempted - transmissions into a multi-scale geo-hashed grid so that displaying data for any region on the globe - requires a (roughly) constant and relatively small volume of data downloaded. The server is deployed - on Heroku with SQS buffering and summary data is served directly from S3. - - On the node side, - MapTheThings pairs a bluetooth and LoRa enabled node with an iOS app that tracks location and - drives transmission of packets. A GPS-equipped LoRa node can also send location packets, but in - this use case there is no tracking of attempted transmissions. - - The differnce between this and TTN Mapper is that the system stores information about failing uplinks, as well as succesful uplink. This is very useful for network modeling. - Status: Broken by V3 update - Nextsteps: - - Update to support TTN V3 - - Do more LoRa walking. - - Data re-processing tools. - - Improve scalability (Lambda + merging infrastructure like Kinesis or MR). - - Data slicing features. - Repositories: - - https://github.com/things-nyc/mapthethings-server - - https://github.com/things-nyc/mapthethings-ios - - https://github.com/things-nyc/mapthethings-arduino -... diff --git a/docs/_data/repos.yml b/docs/_data/repos.yml deleted file mode 100644 index fa7d67c..0000000 --- a/docs/_data/repos.yml +++ /dev/null @@ -1,184 +0,0 @@ ---- -# There are some non-things-nyc repos that we'd like to feature on the website -mcci-catena/arduino-lmic: - description: > - Arduino library implementing LoRaWAN network stack. - Directly operates Semtech SX127x radio chips. - html_url: https://github.com/mcci-catena/arduino-lmic - topics: - - Arduino - - Library - -mcci-catena/arduino-lorawan: - description: > - C++ wrapper with nicer APIs for arduino-lmic. Really just a fancy shim, - but it centralizes a number of ugly details. - html_url: https://github.com/mcci-catena/arduino-lorawan - topics: - - Arduino - - Library - -TheThingsNetwork/arduino-device-lib: - description: > - Arduino Library for TTN Devices using the RN2483 radio. - html_url: https://github.com/TheThingsNetwork/arduino-device-lib - topics: - - Arduino - - Data - - Library - -frankleonrose/LoraStack: - html_url: https://github.com/frankleonrose/LoraStack - description: > - A library that implements the 'arduino-device-lib' high level API, - but down below uses LMiC for direct control of SX127x radios. - Uses PlatformIO to standardize and simplify dependency management. - topics: - - Arduino - - PlatformIO - - Library - -frankleonrose/TemperatureThing: - html_url: https://github.com/frankleonrose/TemperatureThing - description: > - Arduino code for a basic temperature monitoring node. Runs on an - Adafruit Feather LoRa and expects to communicate via SPI with FRAM - chip to store LoRaWAN operational parameters. - topics: - - Node - - PlatformIO - -frankleonrose/ManhattanMapper: - html_url: https://github.com/frankleonrose/ManhattanMapper - description: > - Car-based coverage mapping node for New York City - topics: - - Node - - Mapping - - PlatformIO - -IthacaThings/ttn-multitech-cm: - html_url: https://github.com/IthacaThings/ttn-multitech-cm - description: > - A system supporting the deployment, monitoring, and maintenance of - a fleet of Multi-Tech Conduit and Conduit AP gateways. As part of - deploying hundreds of gateways to cover NYC and Ithaca regions of - New York State, the group manages these gateways as a service to - gateway owners. The system uses the Ansible Configuration - Management tool to drive gateway configuration, an SSH jumphost to - enable secure remote access. - topics: - - Gateway - -IthacaThings/meta-ttni: - html_url: https://github.com/IthacaThings/meta-ttni - description: > - A Yocto layer to build mLinux images for Multi-Tech Conduit and - Conduit AP gateways pre-configured for management with ttn-multitech-cm. - topics: - - Gateway - -jchonig/docker-meetup-slack: - html_url: https://github.com/jchonig/docker-meetup-slack - description: >- - A python script that posts reminders about Meetup meetings to - Slack channels. Used by thingsnyc and ttni (TTN Ithaca). - topics: - - Slack - - Meetup - -# Adding topics using data file because Github Metadata plugin does not (yet) fetch repo topics -things-nyc/ttn-post-adapter: - topics: - - Server - - Data - -things-nyc/heat-seek-feather-m0-lora: - topics: - - Node - -things-nyc/mapthethings-server: - topics: - - Mapping - - Server - -things-nyc/mapthethings-arduino: - topics: - - Mapping - - Node - - PlatformIO - -things-nyc/mapthethings-ios: - topics: - - Mapping - - App - -things-nyc/loramote_sigmap: - topics: - - Mapping - - Node - -things-nyc/multitech-installer: - topics: - - Gateway - -# Lots of the repos don't need to be featured on the website -things-nyc/arduino-lmic: - exclude: true - -things-nyc/blog: - exclude: true - -things-nyc/Adafruit_BME280_Library: - exclude: true - -things-nyc/arduino_and_pc_minimal_gateway: - exclude: true - -things-nyc/boston-dec-2016-demo: - exclude: true - -things-nyc/budget_node: - exclude: true - -things-nyc/collateral-archive: - exclude: true - -things-nyc/initial-state-example: - exclude: true - -things-nyc/mapthethings-web-client: - exclude: true - -things-nyc/proptest: - exclude: true - -things-nyc/random-eui64: - exclude: true - -things-nyc/sigmap: - exclude: true - -things-nyc/testnode-arm-cortex-mbed-lmic-1.5: - exclude: true - -things-nyc/things-nyc-docs: - exclude: true - -things-nyc/things-nyc-workgroup: - exclude: true - -things-nyc/things-nyc.github.io: - exclude: true - -things-nyc/ttn-http-nodejs-middleware: - exclude: true - -things-nyc/ttn-sms-hackathon: - exclude: true - -things-nyc/wiki: - exclude: true - topics: - - SHOULD_NOT_SHOW -... diff --git a/docs/_includes/google_analytics.html b/docs/_includes/google_analytics.html deleted file mode 100644 index 36c97f6..0000000 --- a/docs/_includes/google_analytics.html +++ /dev/null @@ -1,11 +0,0 @@ - - - diff --git a/docs/_includes/menubar.html b/docs/_includes/menubar.html deleted file mode 100644 index b76de38..0000000 --- a/docs/_includes/menubar.html +++ /dev/null @@ -1,114 +0,0 @@ -{% if page.url != "/" %} -{% assign nav_color = "bg-primary text-white" %} -{% else %} -{% assign nav_color = "bg-secondary text-white" %} -{% endif %} - -
diff --git a/docs/_includes/share.html b/docs/_includes/share.html deleted file mode 100644 index 454dfa4..0000000 --- a/docs/_includes/share.html +++ /dev/null @@ -1,17 +0,0 @@ -|
-
- [Manhattan Mapper](https://github.com/frankleonrose/ManhattanMapper)
-
-
- - Configures TTN with app ID and device ID
- - Defines Respire mode control structure
- - Input functions reading current state of the world: GPS and buttons
- - Output functions performing actions triggered by Respire: Sending packets, updating screen, writing to SD card
-
- | ||||
- [LoRaStack](https://github.com/frankleonrose/LoRaStack)
-
- - LoRaWAN library presenting an API comparable to [TTN Arduino Device Lib](https://github.com/TheThingsNetwork/arduino-device-lib/blob/master/src/TheThingsNetwork.h#L46) on devices using SX1276 chips.
-
- |
-
- [Respire](https://github.com/frankleonrose/Respire)
-
- - A state management library
- - Declarative expression of application behavior
- - Isolation of input and output operations
-
- |
-
- [Adafruit GPS](https://github.com/adafruit/Adafruit_GPS)
-
- - Parses serial text stream from GPS unit.
-
- |
-
- [SdFat](https://github.com/greiman/SdFat)
-
- - The SD card library to use.
- - The Arduino default library is simply broken in the context of shared SPI lines.
-
- |
-|
- [MCCI LoRaWAN](https://github.com/mcci-catena/arduino-lorawan)
-
- - LoRaWAN class library the encapsulates much of the process flow required to use LMiC.
-
- |
-
- [Parameter Store](https://github.com/frankleonrose/ParameterStore)
-
- - General purpose Arduino library for storing parameter values by keyword.
- - Writes to FRAM, Bluetooth NVRAM
- - Manhattan Mapper writes to RAM and then load/stores a serialized version from/to SD card
-
- |
-|||
- [MCCI LMiC](https://github.com/mcci-catena/arduino-lmic)
-
- - Core LoRaWAN code from IBM adapted by Matthijs Kooijman and enhanced greatly by Terry Moore.
-
- |
-
- [Timer](https://github.com/JChristensen/Timer)
-
- - Basic timer library.
-
- |
-|||
It's now becoming obvious that the 5G Internet of Things -promised by telcos a few years ago was nothing more than a way to -sell a new generation of smartphones. For several reasons, not -least being the cost involved, no IoT system widely distributed in -the field can be based on devices with the power and maintenance -requirements of 5G transmission.
- - - -The real future of IoT lies at the other end of the power/cost -range in networks of cheap, low-power, long-range sensors based on -a technology that overcomes signal interference among a large -number of transmitters in close proximity and allows seamless -provision and maintenance of the gateways used to provide backhaul -to the internet or to local data processing systems.
- -New York City's FloodNet project is an early example of -real-world IoT in action. To meet the increasing challenge of -urban flooding, a network of sensors has been installed in -flood-prone areas of the city to collect data on the presence, -depth, and duration of street-level flood events.
- -The 81 sensors so far installed by the project communicate -through a network of 17 gateways distributed across the five -boroughs. They have already recorded flooding caused by high -tides, stormwater runoff, storm surge, and extreme -precipitation. The data is publicly visible and available in a -form that can be used by multiple agencies for flood resiliency -planning and emergency response.
- -The FloodNet project is an excellent example of appropriate -technology. Existing water level sensors, such as those used by -USGS stream gauges, are far too bulky and expensive to be deployed -at scale across urban areas. The city needed cheap, accurate, -weatherproof, real-time flood sensors designed for long-term -unattended deployment independent of existing power and network -infrastructure, adaptable to many use cases, and featuring a -simple, open-source design.
- -The solution: solar-powered, pole-mounted ultrasonic -rangefinder modules assembled from off-the-shelf components at a -cost of less than USD200 apiece. (Members of The Things Network NY -assisted in the design of these devices. Plans are available from -FloodNet's Github page.)
- -The techologies that made this possible: LoRaWAN and The Things -Network.
- -Once a minute, a radio unit in each sensor module sends a -single item of encrypted data to the network of gateways (any -gateway can handle any remote sensor as long as the sensor is -located, in this densely built environment, within about 2 km of -the gateway). Data from the gateways is forwarded through The -Things Network to project servers hosted by New York University, -from which the data is made public over the -internet using a variety of open-source tools such as Docker and -Grafana.
- -FloodNet's plans for the future include expansion of the -network to provide finer-grained coverage of the five boroughs and -an iteration of sensor design to improve performance and lower the -cost even further through manufacturing at scale.
- -Projects such as FloodNet show how the "smart city" concept can -become a practical reality through the adoption of appropriate -technologies. For a complete account of FloodNet, including -insights relevant to similar efforts, see -the FloodNet tech paper.
- -
-
--Photos from the full FloodNet report. (A) Closeup of the FloodNet -sensor, showing the (i) ultrasonic sensor cone, (ii) sensor -housing, (iii) solar panel for battery charging, and (iv) antenna -for data transmission. (B) Signage that is installed with each -sensor. (C) FloodNet engineers installing a sensor in the -field.(D) FloodNet sensor and sign installed on a U-channel pole -in the Bronx, NY. -diff --git a/docs/_stories/2024-02-25_2020-lexus-eco-challenge.html b/docs/_stories/2024-02-25_2020-lexus-eco-challenge.html deleted file mode 100644 index d5c30dc..0000000 --- a/docs/_stories/2024-02-25_2020-lexus-eco-challenge.html +++ /dev/null @@ -1,20 +0,0 @@ ---- -layout: story -title: "Jersey City PS-28 Middleschoolers Win Lexus Eco Challenge using TTN" -author: jeffhonig -excerpt_separator: ---- -
The Things Network New York helped stablize the a gateway with poor -cellular coverage during the 2020 Lexus Eco Challenge helping the -R.E.M. Remote Environmental Monitoring team from P.S. 28 Christa -McAuliffe School in Jersey City, New Jersey with the middle-school -Grand Prize.
- - - -More info to come, in the mean time, read about the challenge here: - -GREEN FOR GOING GREEN – WINNING STUDENTS TACKLE GLOBAL ENVIRONMENTAL ISSUES IN 2020 LEXUS ECO CHALLENGE -
:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing)*1)*var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing)*1)*calc(1 - var(--tw-space-y-reverse)))}.gap-x-3{column-gap:calc(var(--spacing)*3)}.gap-y-1{row-gap:calc(var(--spacing)*1)}.overflow-auto{overflow:auto}.overflow-hidden{overflow:hidden}.overflow-x-auto{overflow-x:auto}.overscroll-x-contain{overscroll-behavior-x:contain}.scroll-smooth{scroll-behavior:smooth}.rounded-2xl{border-radius:var(--radius-2xl)}.rounded-full{border-radius:3.40282e38px}.rounded-lg{border-radius:var(--radius-lg)}.rounded-md{border-radius:var(--radius-md)}.rounded-xl{border-radius:var(--radius-xl)}.rounded-t-xl{border-top-left-radius:var(--radius-xl);border-top-right-radius:var(--radius-xl)}.border{border-style:var(--tw-border-style);border-width:1px}.border-t{border-top-style:var(--tw-border-style);border-top-width:1px}.border-b{border-bottom-style:var(--tw-border-style);border-bottom-width:1px}.border-slate-200{border-color:var(--color-slate-200)}.border-white{border-color:var(--color-white)}.bg-black{background-color:var(--color-black)}.bg-black\/40{background-color:#0006}@supports (color:color-mix(in lab,red,red)){.bg-black\/40{background-color:color-mix(in oklab,var(--color-black)40%,transparent)}}.bg-blue-100{background-color:var(--color-blue-100)}.bg-slate-50{background-color:var(--color-slate-50)}.bg-slate-100{background-color:var(--color-slate-100)}.bg-white{background-color:var(--color-white)}.bg-gradient-to-b{--tw-gradient-position:to bottom in oklab;background-image:linear-gradient(var(--tw-gradient-stops))}.bg-gradient-to-t{--tw-gradient-position:to top in oklab;background-image:linear-gradient(var(--tw-gradient-stops))}.from-black\/20{--tw-gradient-from:#0003}@supports (color:color-mix(in lab,red,red)){.from-black\/20{--tw-gradient-from:color-mix(in oklab,var(--color-black)20%,transparent)}}.from-black\/20{--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position),var(--tw-gradient-from)var(--tw-gradient-from-position),var(--tw-gradient-to)var(--tw-gradient-to-position))}.to-blue-100{--tw-gradient-to:var(--color-blue-100);--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position),var(--tw-gradient-from)var(--tw-gradient-from-position),var(--tw-gradient-to)var(--tw-gradient-to-position))}.to-transparent{--tw-gradient-to:transparent;--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position),var(--tw-gradient-from)var(--tw-gradient-from-position),var(--tw-gradient-to)var(--tw-gradient-to-position))}.object-cover{object-fit:cover}.p-4{padding:calc(var(--spacing)*4)}.p-5{padding:calc(var(--spacing)*5)}.px-1{padding-inline:calc(var(--spacing)*1)}.px-2{padding-inline:calc(var(--spacing)*2)}.px-3{padding-inline:calc(var(--spacing)*3)}.px-4{padding-inline:calc(var(--spacing)*4)}.py-0\.5{padding-block:calc(var(--spacing)*.5)}.py-1\.5{padding-block:calc(var(--spacing)*1.5)}.py-2{padding-block:calc(var(--spacing)*2)}.py-3{padding-block:calc(var(--spacing)*3)}.py-5{padding-block:calc(var(--spacing)*5)}.py-12{padding-block:calc(var(--spacing)*12)}.py-14{padding-block:calc(var(--spacing)*14)}.py-16{padding-block:calc(var(--spacing)*16)}.pl-5{padding-left:calc(var(--spacing)*5)}.text-center{text-align:center}.text-2xl{font-size:var(--text-2xl);line-height:var(--tw-leading,var(--text-2xl--line-height))}.text-3xl{font-size:var(--text-3xl);line-height:var(--tw-leading,var(--text-3xl--line-height))}.text-4xl{font-size:var(--text-4xl);line-height:var(--tw-leading,var(--text-4xl--line-height))}.text-5xl{font-size:var(--text-5xl);line-height:var(--tw-leading,var(--text-5xl--line-height))}.text-base{font-size:var(--text-base);line-height:var(--tw-leading,var(--text-base--line-height))}.text-lg{font-size:var(--text-lg);line-height:var(--tw-leading,var(--text-lg--line-height))}.text-sm{font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}.text-xl{font-size:var(--text-xl);line-height:var(--tw-leading,var(--text-xl--line-height))}.text-xs{font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height))}.leading-none{--tw-leading:1;line-height:1}.leading-relaxed{--tw-leading:var(--leading-relaxed);line-height:var(--leading-relaxed)}.leading-snug{--tw-leading:var(--leading-snug);line-height:var(--leading-snug)}.leading-tight{--tw-leading:var(--leading-tight);line-height:var(--leading-tight)}.font-medium{--tw-font-weight:var(--font-weight-medium);font-weight:var(--font-weight-medium)}.font-semibold{--tw-font-weight:var(--font-weight-semibold);font-weight:var(--font-weight-semibold)}.tracking-tight{--tw-tracking:var(--tracking-tight);letter-spacing:var(--tracking-tight)}.text-black{color:var(--color-black)}.text-blue-500{color:var(--color-blue-500)}.text-slate-300{color:var(--color-slate-300)}.text-slate-500{color:var(--color-slate-500)}.text-slate-600{color:var(--color-slate-600)}.text-slate-700{color:var(--color-slate-700)}.text-slate-900{color:var(--color-slate-900)}.text-white{color:var(--color-white)}.underline{text-decoration-line:underline}.underline-offset-2{text-underline-offset:2px}.opacity-0{opacity:0}.shadow-xl{--tw-shadow:0 20px 25px -5px var(--tw-shadow-color,#0000001a),0 8px 10px -6px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.backdrop-blur-sm{--tw-backdrop-blur:blur(var(--blur-sm));-webkit-backdrop-filter:var(--tw-backdrop-blur,)var(--tw-backdrop-brightness,)var(--tw-backdrop-contrast,)var(--tw-backdrop-grayscale,)var(--tw-backdrop-hue-rotate,)var(--tw-backdrop-invert,)var(--tw-backdrop-opacity,)var(--tw-backdrop-saturate,)var(--tw-backdrop-sepia,);backdrop-filter:var(--tw-backdrop-blur,)var(--tw-backdrop-brightness,)var(--tw-backdrop-contrast,)var(--tw-backdrop-grayscale,)var(--tw-backdrop-hue-rotate,)var(--tw-backdrop-invert,)var(--tw-backdrop-opacity,)var(--tw-backdrop-saturate,)var(--tw-backdrop-sepia,)}.transition{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to,opacity,box-shadow,transform,translate,scale,rotate,filter,-webkit-backdrop-filter,backdrop-filter,display,visibility,content-visibility,overlay,pointer-events;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-opacity{transition-property:opacity;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-shadow{transition-property:box-shadow;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-transform{transition-property:transform,translate,scale,rotate;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.select-none{-webkit-user-select:none;user-select:none}.\[scrollbar-color\:theme\(colors\.slate\.200\)_transparent\]{scrollbar-color:oklch(92.9% .013 255.508) transparent}.\[scrollbar-width\:thin\]{scrollbar-width:thin}@media (hover:hover){.group-hover\:scale-\[1\.02\]:is(:where(.group):hover *){scale:1.02}.group-hover\:opacity-5:is(:where(.group):hover *){opacity:.05}.hover\:bg-slate-50:hover{background-color:var(--color-slate-50)}.hover\:text-slate-800:hover{color:var(--color-slate-800)}.hover\:opacity-80:hover{opacity:.8}.hover\:opacity-90:hover{opacity:.9}.hover\:shadow-md:hover{--tw-shadow:0 4px 6px -1px var(--tw-shadow-color,#0000001a),0 2px 4px -2px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.hover\:shadow-sm:hover{--tw-shadow:0 1px 3px 0 var(--tw-shadow-color,#0000001a),0 1px 2px -1px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}}.focus\:ring-1:focus{--tw-ring-shadow:var(--tw-ring-inset,)0 0 0 calc(1px + var(--tw-ring-offset-width))var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.focus\:ring-2:focus{--tw-ring-shadow:var(--tw-ring-inset,)0 0 0 calc(2px + var(--tw-ring-offset-width))var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.focus\:ring-slate-100:focus{--tw-ring-color:var(--color-slate-100)}.focus\:ring-slate-300:focus{--tw-ring-color:var(--color-slate-300)}.focus\:outline-none:focus{--tw-outline-style:none;outline-style:none}.focus-visible\:ring-2:focus-visible{--tw-ring-shadow:var(--tw-ring-inset,)0 0 0 calc(2px + var(--tw-ring-offset-width))var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.focus-visible\:ring-black\/20:focus-visible{--tw-ring-color:#0003}@supports (color:color-mix(in lab,red,red)){.focus-visible\:ring-black\/20:focus-visible{--tw-ring-color:color-mix(in oklab,var(--color-black)20%,transparent)}}.focus-visible\:ring-black\/60:focus-visible{--tw-ring-color:#0009}@supports (color:color-mix(in lab,red,red)){.focus-visible\:ring-black\/60:focus-visible{--tw-ring-color:color-mix(in oklab,var(--color-black)60%,transparent)}}@media (prefers-reduced-motion:no-preference){.motion-safe\:duration-200{--tw-duration:.2s;transition-duration:.2s}.motion-safe\:duration-300{--tw-duration:.3s;transition-duration:.3s}}@media (prefers-reduced-motion:reduce){.motion-reduce\:transform-none{transform:none}}@media (min-width:40rem){.sm\:flex{display:flex}.sm\:w-\[310px\]{width:310px}.sm\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.sm\:grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}.sm\:p-6{padding:calc(var(--spacing)*6)}}@media (min-width:48rem){.md\:hidden{display:none}.md\:h-80{height:calc(var(--spacing)*80)}.md\:w-80{width:calc(var(--spacing)*80)}.md\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.md\:gap-6{gap:calc(var(--spacing)*6)}.md\:gap-10{gap:calc(var(--spacing)*10)}.md\:text-2xl{font-size:var(--text-2xl);line-height:var(--tw-leading,var(--text-2xl--line-height))}.md\:text-3xl{font-size:var(--text-3xl);line-height:var(--tw-leading,var(--text-3xl--line-height))}.md\:text-5xl{font-size:var(--text-5xl);line-height:var(--tw-leading,var(--text-5xl--line-height))}}@media (min-width:64rem){.lg\:grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}}}:root{--text:#111827;--muted:#6b7280;--border:#e5e7eb;--bg:#fff;--primary:#111827}*{box-sizing:border-box}html,body,#root{height:100%}body{color:var(--text);background:var(--bg);margin:0;font-family:ui-sans-serif,system-ui,-apple-system,Segoe UI,Roboto,Helvetica,Arial,Apple Color Emoji,Segoe UI Emoji}.app-root{flex-direction:column;min-height:100%;display:flex}.container{flex:1 0 auto;max-width:1040px;margin:0 auto;padding:24px 16px}.hero{padding:56px 0 24px}.hero-title{margin:0 0 12px;font-size:clamp(28px,6vw,42px);font-weight:700;line-height:1.1}.hero-subtitle{color:var(--muted);max-width:48ch;margin:0 0 24px;font-size:clamp(16px,2.4vw,20px)}.hero-cta{flex-wrap:wrap;gap:12px;display:flex}.btn{border:1px solid var(--border);border-radius:8px;padding:10px 14px;font-weight:600;text-decoration:none;display:inline-block}.btn-primary{background:var(--primary);color:#fff;border-color:var(--primary)}.btn-outline{color:var(--text);background:#fff}.btn:hover{transition:transform .12s;transform:translateY(-1px)}@property --tw-scroll-snap-strictness{syntax:"*";inherits:false;initial-value:proximity}@property --tw-space-y-reverse{syntax:"*";inherits:false;initial-value:0}@property --tw-border-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-gradient-position{syntax:"*";inherits:false}@property --tw-gradient-from{syntax:"`s get reset. However, we also reset the\n// bottom margin to use `rem` units instead of `em`.\n\np {\n margin-top: 0;\n margin-bottom: $paragraph-margin-bottom;\n}\n\n\n// Abbreviations\n//\n// 1. Add the correct text decoration in Chrome, Edge, Opera, and Safari.\n// 2. Add explicit cursor to indicate changed behavior.\n// 3. Prevent the text-decoration to be skipped.\n\nabbr[title] {\n text-decoration: underline dotted; // 1\n cursor: help; // 2\n text-decoration-skip-ink: none; // 3\n}\n\n\n// Address\n\naddress {\n margin-bottom: 1rem;\n font-style: normal;\n line-height: inherit;\n}\n\n\n// Lists\n\nol,\nul {\n padding-left: 2rem;\n}\n\nol,\nul,\ndl {\n margin-top: 0;\n margin-bottom: 1rem;\n}\n\nol ol,\nul ul,\nol ul,\nul ol {\n margin-bottom: 0;\n}\n\ndt {\n font-weight: $dt-font-weight;\n}\n\n// 1. Undo browser default\n\ndd {\n margin-bottom: .5rem;\n margin-left: 0; // 1\n}\n\n\n// Blockquote\n\nblockquote {\n margin: 0 0 1rem;\n}\n\n\n// Strong\n//\n// Add the correct font weight in Chrome, Edge, and Safari\n\nb,\nstrong {\n font-weight: $font-weight-bolder;\n}\n\n\n// Small\n//\n// Add the correct font size in all browsers\n\nsmall {\n @include font-size($small-font-size);\n}\n\n\n// Mark\n\nmark {\n padding: $mark-padding;\n background-color: var(--#{$prefix}highlight-bg);\n}\n\n\n// Sub and Sup\n//\n// Prevent `sub` and `sup` elements from affecting the line height in\n// all browsers.\n\nsub,\nsup {\n position: relative;\n @include font-size($sub-sup-font-size);\n line-height: 0;\n vertical-align: baseline;\n}\n\nsub { bottom: -.25em; }\nsup { top: -.5em; }\n\n\n// Links\n\na {\n color: var(--#{$prefix}link-color);\n text-decoration: $link-decoration;\n\n &:hover {\n color: var(--#{$prefix}link-hover-color);\n text-decoration: $link-hover-decoration;\n }\n}\n\n// And undo these styles for placeholder links/named anchors (without href).\n// It would be more straightforward to just use a[href] in previous block, but that\n// causes specificity issues in many other styles that are too complex to fix.\n// See https://github.com/twbs/bootstrap/issues/19402\n\na:not([href]):not([class]) {\n &,\n &:hover {\n color: inherit;\n text-decoration: none;\n }\n}\n\n\n// Code\n\npre,\ncode,\nkbd,\nsamp {\n font-family: $font-family-code;\n @include font-size(1em); // Correct the odd `em` font sizing in all browsers.\n}\n\n// 1. Remove browser default top margin\n// 2. Reset browser default of `1em` to use `rem`s\n// 3. Don't allow content to break outside\n\npre {\n display: block;\n margin-top: 0; // 1\n margin-bottom: 1rem; // 2\n overflow: auto; // 3\n @include font-size($code-font-size);\n color: $pre-color;\n\n // Account for some code outputs that place code tags in pre tags\n code {\n @include font-size(inherit);\n color: inherit;\n word-break: normal;\n }\n}\n\ncode {\n @include font-size($code-font-size);\n color: var(--#{$prefix}code-color);\n word-wrap: break-word;\n\n // Streamline the style when inside anchors to avoid broken underline and more\n a > & {\n color: inherit;\n }\n}\n\nkbd {\n padding: $kbd-padding-y $kbd-padding-x;\n @include font-size($kbd-font-size);\n color: $kbd-color;\n background-color: $kbd-bg;\n @include border-radius($border-radius-sm);\n\n kbd {\n padding: 0;\n @include font-size(1em);\n font-weight: $nested-kbd-font-weight;\n }\n}\n\n\n// Figures\n//\n// Apply a consistent margin strategy (matches our type styles).\n\nfigure {\n margin: 0 0 1rem;\n}\n\n\n// Images and content\n\nimg,\nsvg {\n vertical-align: middle;\n}\n\n\n// Tables\n//\n// Prevent double borders\n\ntable {\n caption-side: bottom;\n border-collapse: collapse;\n}\n\ncaption {\n padding-top: $table-cell-padding-y;\n padding-bottom: $table-cell-padding-y;\n color: $table-caption-color;\n text-align: left;\n}\n\n// 1. Removes font-weight bold by inheriting\n// 2. Matches default `