diff --git a/.gitignore b/.gitignore
index 7ea0b16d..8859a42a 100644
--- a/.gitignore
+++ b/.gitignore
@@ -71,6 +71,9 @@ typings/
# nuxt.js build output
.nuxt
+# Nuxt 3 build output
+.output
+
# Nuxt generate
dist
diff --git a/CLAUDE.md b/CLAUDE.md
new file mode 100644
index 00000000..fbf6aa28
--- /dev/null
+++ b/CLAUDE.md
@@ -0,0 +1,161 @@
+# CLAUDE.md
+
+This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
+
+## Project Overview
+
+This is the Lansing Codes community website - a resource hub for coders and tech enthusiasts in Lansing, Michigan. The site features a calendar of tech events, meetup groups, local resources, sponsor information, and community engagement tools.
+
+## Tech Stack
+
+- **Framework**: Nuxt 3 (Vue 3)
+- **Styling**: Tailwind CSS with custom SCSS
+- **Database**: Firebase Firestore (read-only production data by default in development)
+- **Data Management**: VueFire for Firestore integration, migrating from legacy Vuexfire
+- **Icons**: FontAwesome via `@fortawesome/vue-fontawesome`
+- **Testing**: Playwright for UI testing
+- **Node Version**: >= 22.18.0
+
+## Architecture
+
+### Migration Status (Nuxt 2 → Nuxt 3)
+
+This codebase is **currently being migrated** from Nuxt 2 to Nuxt 3:
+
+- **Legacy patterns**: `store/` directory still contains Vuex stores using `vuexfire` (old pattern)
+- **New patterns**: `composables/` directory contains Composition API composables using `vuefire` (new pattern)
+- Both patterns exist side-by-side during the migration
+- Prefer using composables for new features; gradually migrate store usage to composables
+
+### Data Flow
+
+**Firebase Integration**:
+- Firestore database connection configured in [utils/firestore.js](utils/firestore.js)
+- Firebase app initialized in [plugins/vuefire.client.js](plugins/vuefire.client.js)
+- Default environment points to production read-only data
+- Custom Firebase config can be provided via `FIREBASE_WEB_CONFIG` environment variable
+
+**Data Loading Patterns**:
+1. **New (Nuxt 3)**: Composables in `composables/` directory
+ - `useEvents()`: Loads upcoming events from Firestore
+ - `useGroups()`: Loads meetup groups
+ - `useSponsors()`: Loads sponsor information
+ - Use VueFire's `useCollection()` for reactive Firestore queries
+
+2. **Legacy (Nuxt 2)**: Vuex stores in `store/` directory
+ - Still present but being phased out
+ - Use firestoreAction from vuexfire
+
+**Event Filtering**:
+- Events are filtered by date range: today through the end of the configured number of weeks
+- Maximum calendar weeks configured in [config/max-calendar-weeks.js](config/max-calendar-weeks.js)
+- Uses `date-fns` for date manipulation
+
+### Component Structure
+
+**Page Structure**:
+- Single layout: [layouts/default.vue](layouts/default.vue) with header (Navigation) and footer
+- Homepage ([pages/index.vue](pages/index.vue)) is composed of section components:
+ - Welcome
+ - Events (calendar and list views)
+ - Meetups
+ - Resources
+ - Sponsors
+ - Newsletter
+
+**Component Organization**:
+- Section components in `components/` directory (e.g., `events.vue`, `meetups.vue`)
+- Reusable sub-components (e.g., `event-calendar.vue`, `event-list.vue`, `card--event.vue`)
+- Logo components with size variants (`logo--small.vue`, `logo--medium.vue`, etc.)
+
+### Styling
+
+- Global styles in [layouts/default.vue](layouts/default.vue)
+- Tailwind configuration in [tailwind.config.js](tailwind.config.js)
+- Main SCSS entry point: `assets/scss/tailwind.scss`
+- Custom CSS classes:
+ - `.lc-bg-ltr-gradient`: Left-to-right blue gradient
+ - `.lc-bg-right-triangle`, `.lc-bg-left-triangle`, `.lc-bg-down-triangle`: Triangle background patterns
+ - `.sr-only`: Screen reader only content
+
+### Configuration
+
+- **SSR**: Disabled (`ssr: false` in nuxt.config.ts)
+- **Firebase config**: Hardcoded in nuxt.config.ts under `runtimeConfig.public.firebaseConfig`
+- **Resources**: Static resource data in [config/resources.js](config/resources.js)
+- **Fonts**: External fonts loaded from CDN (Lansing Codes webfont, Font Mfizz, Montserrat)
+
+## Common Commands
+
+### Development
+```sh
+npm run dev
+```
+Runs dev server at http://localhost:3000 with hot reload
+
+### Build
+```sh
+npm run build
+```
+Builds production site (output in `.output/` directory)
+
+### Generate Static Site
+```sh
+npm run generate
+```
+Generates static files for deployment
+
+### Preview Production Build
+```sh
+npm run preview
+```
+Previews the production build locally
+
+### Linting
+```sh
+npm run lint # Check for linting errors
+npm run lintfix # Auto-fix linting errors
+```
+Linting runs automatically on `git commit` via the `precommit` hook
+
+### Testing
+
+
+## Git Workflow
+
+- **Main branch**: `main` - snapshot of latest in-flight release
+- **Production branch**: `production` - live production code
+- **Development**: Create feature branches from `main`
+- **Deployment**: PRs merge to `main` → auto-deploy to staging → manual promotion to `production`
+
+### Contributors
+
+When contributing, add your name to the `contributors` array in [package.json](package.json)
+
+### Branch Promotion to Production
+```sh
+git fetch origin && git push --force origin origin/main:production
+```
+
+## Deployment
+
+- **Staging**: Auto-deployed to Netlify on merge to `main`
+ - URL: lansingcodes-staging.netlify.com
+ - All branches get preview deployments
+- **Production**: Auto-deployed to Netlify when `production` branch is updated
+ - URL: www.lansing.codes
+- **Build command**: `npm run build`
+- **Deploy directory**: `/dist` (Nuxt 2) or `/.output` (Nuxt 3)
+
+## Utilities
+
+Located in `utils/` directory:
+- `clean-event-description.js`: Sanitizes event description HTML
+- `format-readable-date-time.js`: Formats timestamps into readable strings
+- `group-for-event.js`: Matches events to their parent meetup groups
+- `simplified-name.js`: Normalizes names for comparison
+- `firestore.js`: Firebase/Firestore initialization and exports
+
+## Code of Conduct
+
+All contributors must follow the [Code of Conduct](https://www.lansing.codes/code-of-conduct/). Treat all participants with respect.
diff --git a/app.vue b/app.vue
new file mode 100644
index 00000000..f8eacfa7
--- /dev/null
+++ b/app.vue
@@ -0,0 +1,5 @@
+
+
+
+
+
diff --git a/app/router.scrollBehavior.js b/app/router.scrollBehavior.js
index 0ada7085..7066b2a1 100644
--- a/app/router.scrollBehavior.js
+++ b/app/router.scrollBehavior.js
@@ -2,7 +2,7 @@
// https://nuxtjs.org/api/configuration-router#scrollbehavior
// Without this explicitly provided, though, using the back button in
// Chrome does not work when navigating different sections of the page.
-export default function (to, from, savedPosition) {
+export default function(to, from, savedPosition) {
// if the returned position is falsy or an empty object,
// will retain current scroll position.
let position = false
@@ -11,7 +11,7 @@ export default function (to, from, savedPosition) {
if (to.matched.length < 2) {
// scroll to the top of the page
position = { x: 0, y: 0 }
- } else if (to.matched.some((r) => r.components.default.options.scrollToTop)) {
+ } else if (to.matched.some(r => r.components.default.options.scrollToTop)) {
// if one of the children has scrollToTop option set to true
position = { x: 0, y: 0 }
}
@@ -21,7 +21,7 @@ export default function (to, from, savedPosition) {
position = savedPosition
}
- return new Promise((resolve) => {
+ return new Promise(resolve => {
// wait for the out transition to complete (if necessary)
window.$nuxt.$once('triggerScroll', () => {
// coords will be used if no selector is provided,
diff --git a/assets/scss/tailwind.scss b/assets/scss/tailwind.scss
index 5c3a43b0..237528f9 100644
--- a/assets/scss/tailwind.scss
+++ b/assets/scss/tailwind.scss
@@ -4,9 +4,9 @@
*
* If using `postcss-import`, use this import instead:
*
- * @import "tailwindcss/preflight";
+ * @import "tailwindcss/base";
*/
-@tailwind preflight;
+@tailwind base;
/**
* This injects any component classes registered by plugins.
diff --git a/assets/scss/utilities/transforms.scss b/assets/scss/utilities/transforms.scss
index 9d0698ab..3b469105 100644
--- a/assets/scss/utilities/transforms.scss
+++ b/assets/scss/utilities/transforms.scss
@@ -22,14 +22,26 @@
transform: translateY(100vh);
}
-@variants active, hover {
+@layer utilities {
.slide-down-px {
transform: translateY(1px);
transition: all ease-in-out .1s;
}
+ .active\:slide-down-px:active,
+ .hover\:slide-down-px:hover {
+ transform: translateY(1px);
+ transition: all ease-in-out .1s;
+ }
+
.slide-up-px {
transform: translateY(-1px);
transition: all ease-in-out .1s;
}
+
+ .active\:slide-up-px:active,
+ .hover\:slide-up-px:hover {
+ transform: translateY(-1px);
+ transition: all ease-in-out .1s;
+ }
}
diff --git a/components/calendar--event.vue b/components/calendar--event.vue
index 3222271e..963ee9b1 100644
--- a/components/calendar--event.vue
+++ b/components/calendar--event.vue
@@ -1,157 +1,141 @@
Send contributions via
PayPalPayPal
to Humanity Codes
@@ -259,25 +295,19 @@
-
diff --git a/plugins/font-awesome.js b/plugins/font-awesome.js
index 7fac72e0..ecb16b57 100644
--- a/plugins/font-awesome.js
+++ b/plugins/font-awesome.js
@@ -1,12 +1,11 @@
/************************************************************************
- Font Awesome 5 SVG Icons
+ Font Awesome 6 SVG Icons
Based on https://fontawesome.com/how-to-use/on-the-web/using-with/vuejs
*************************************************************************/
-// need this for the plugin to work
-import Vue from 'vue'
// import core SVG icons
import { library } from '@fortawesome/fontawesome-svg-core'
+import { FontAwesomeIcon } from '@fortawesome/vue-fontawesome'
/*******************************************************************
👉 Import the icons you want to use from the appropriate set,
@@ -20,7 +19,7 @@ import { library } from '@fortawesome/fontawesome-svg-core'
import {
faCalendarAlt,
faGrinBeamSweat,
- faThumbsUp,
+ faThumbsUp
} from '@fortawesome/free-regular-svg-icons'
library.add(faCalendarAlt, faGrinBeamSweat, faThumbsUp)
@@ -54,7 +53,7 @@ import {
faUnlockAlt,
faUserCircle,
faUserFriends,
- faUsers,
+ faUsers
} from '@fortawesome/free-solid-svg-icons'
library.add(
@@ -99,7 +98,7 @@ import {
faSlack,
faTwitter,
faWordpressSimple,
- faYoutube,
+ faYoutube
} from '@fortawesome/free-brands-svg-icons'
library.add(
@@ -127,6 +126,6 @@ library.add(
See https://github.com/FortAwesome/vue-fontawesome for more tips.
***************************************************************************/
-// Import and globally register a component called font-awesome-icon
-import { FontAwesomeIcon } from '@fortawesome/vue-fontawesome'
-Vue.component('FontAwesomeIcon', FontAwesomeIcon)
+export default defineNuxtPlugin((nuxtApp) => {
+ nuxtApp.vueApp.component('FontAwesomeIcon', FontAwesomeIcon)
+})
diff --git a/plugins/popover.js b/plugins/popover.js
index 6be98e1d..d1f0c1d3 100644
--- a/plugins/popover.js
+++ b/plugins/popover.js
@@ -1,4 +1,6 @@
-import Vue from 'vue'
-import Popover from 'vue-js-popover'
-
-Vue.use(Popover)
+// Legacy popover plugin - no longer used
+// Popover functionality is now handled by vue3-popper directly in components
+// See components/calendar--event.vue for implementation
+export default defineNuxtPlugin(() => {
+ // Empty plugin - kept for backward compatibility during migration
+})
diff --git a/plugins/vuefire.client.js b/plugins/vuefire.client.js
new file mode 100644
index 00000000..72aa29f0
--- /dev/null
+++ b/plugins/vuefire.client.js
@@ -0,0 +1,21 @@
+import { VueFire, VueFireAuth } from 'vuefire'
+import { initializeApp } from 'firebase/app'
+
+const firebaseConfig = {
+ apiKey: 'AIzaSyCMw8mZ1D1GAYpeotAqVCaYAMtn3URVOok',
+ authDomain: 'lansing-codes.firebaseapp.com',
+ databaseURL: 'https://lansing-codes.firebaseio.com',
+ projectId: 'lansing-codes',
+ storageBucket: 'lansing-codes.appspot.com',
+ messagingSenderId: '647280182517',
+ appId: '1:647280182517:web:779f72d0b90c0dd4',
+}
+
+export default defineNuxtPlugin((nuxtApp) => {
+ const firebaseApp = initializeApp(firebaseConfig)
+
+ nuxtApp.vueApp.use(VueFire, {
+ firebaseApp,
+ modules: []
+ })
+})
diff --git a/static/favicon.ico b/public/favicon.ico
similarity index 100%
rename from static/favicon.ico
rename to public/favicon.ico
diff --git a/static/resources-for-lansing-coders.jpg b/public/resources-for-lansing-coders.jpg
similarity index 100%
rename from static/resources-for-lansing-coders.jpg
rename to public/resources-for-lansing-coders.jpg
diff --git a/static/sponsors/a2-hosting.png b/public/sponsors/a2-hosting.png
similarity index 100%
rename from static/sponsors/a2-hosting.png
rename to public/sponsors/a2-hosting.png
diff --git a/static/sponsors/brightdigit.png b/public/sponsors/brightdigit.png
similarity index 100%
rename from static/sponsors/brightdigit.png
rename to public/sponsors/brightdigit.png
diff --git a/static/sponsors/humanity-codes.png b/public/sponsors/humanity-codes.png
similarity index 100%
rename from static/sponsors/humanity-codes.png
rename to public/sponsors/humanity-codes.png
diff --git a/static/sponsors/hyperverses.png b/public/sponsors/hyperverses.png
similarity index 100%
rename from static/sponsors/hyperverses.png
rename to public/sponsors/hyperverses.png
diff --git a/static/sponsors/kla.png b/public/sponsors/kla.png
similarity index 100%
rename from static/sponsors/kla.png
rename to public/sponsors/kla.png
diff --git a/static/sponsors/leap.png b/public/sponsors/leap.png
similarity index 100%
rename from static/sponsors/leap.png
rename to public/sponsors/leap.png
diff --git a/static/sponsors/lmn.png b/public/sponsors/lmn.png
similarity index 100%
rename from static/sponsors/lmn.png
rename to public/sponsors/lmn.png
diff --git a/static/sponsors/mitn.png b/public/sponsors/mitn.png
similarity index 100%
rename from static/sponsors/mitn.png
rename to public/sponsors/mitn.png
diff --git a/static/sponsors/rmc.png b/public/sponsors/rmc.png
similarity index 100%
rename from static/sponsors/rmc.png
rename to public/sponsors/rmc.png
diff --git a/static/sponsors/techsmith.png b/public/sponsors/techsmith.png
similarity index 100%
rename from static/sponsors/techsmith.png
rename to public/sponsors/techsmith.png
diff --git a/static/sponsors/teksystems.png b/public/sponsors/teksystems.png
similarity index 100%
rename from static/sponsors/teksystems.png
rename to public/sponsors/teksystems.png
diff --git a/static/README.md b/static/README.md
deleted file mode 100644
index 3fc50023..00000000
--- a/static/README.md
+++ /dev/null
@@ -1,10 +0,0 @@
-# STATIC
-
-**This directory is not required, you can delete it if you don't want to use it.**
-
-This directory contains your static files.
-Each file inside this directory is mapped to `/`.
-
-Example: `/static/robots.txt` is mapped as `/robots.txt`.
-
-More information about the usage of this directory in [the documentation](https://nuxtjs.org/guide/assets#static).
diff --git a/store/README.md b/store/README.md
deleted file mode 100644
index 111fea1b..00000000
--- a/store/README.md
+++ /dev/null
@@ -1,10 +0,0 @@
-# STORE
-
-**This directory is not required, you can delete it if you don't want to use it.**
-
-This directory contains your Vuex Store files.
-Vuex Store option is implemented in the Nuxt.js framework.
-
-Creating a file in this directory activate the option in the framework automatically.
-
-More information about the usage of this directory in [the documentation](https://nuxtjs.org/guide/vuex-store).
diff --git a/store/events.js b/store/events.js
deleted file mode 100644
index 42fa8ac4..00000000
--- a/store/events.js
+++ /dev/null
@@ -1,21 +0,0 @@
-import { firestoreAction } from 'vuexfire'
-import firestore from '~/utils/firestore'
-import { startOfDay, addWeeks, endOfDay, endOfWeek } from 'date-fns'
-import weeksAvailable from '~/config/max-calendar-weeks'
-
-export const state = () => ({
- upcoming: [],
-})
-
-export const actions = {
- loadUpcoming: firestoreAction((context) => {
- const startDate = startOfDay(Date.now())
- const endDate = endOfDay(endOfWeek(addWeeks(startDate, weeksAvailable - 1)))
- const eventsRef = firestore
- .collection('events')
- .where('startTime', '>=', startDate.getTime())
- .where('startTime', '<=', endDate.getTime())
- .orderBy('startTime', 'asc')
- return context.bindFirestoreRef('upcoming', eventsRef)
- }),
-}
diff --git a/store/groups.js b/store/groups.js
deleted file mode 100644
index 68643e11..00000000
--- a/store/groups.js
+++ /dev/null
@@ -1,12 +0,0 @@
-import { firestoreAction } from 'vuexfire'
-import firestore from '~/utils/firestore'
-
-export const state = () => ({
- all: [],
-})
-
-export const actions = {
- loadAll: firestoreAction((context) =>
- context.bindFirestoreRef('all', firestore.collection('groups'))
- ),
-}
diff --git a/store/index.js b/store/index.js
deleted file mode 100644
index 8ea7c3a6..00000000
--- a/store/index.js
+++ /dev/null
@@ -1,3 +0,0 @@
-import { vuexfireMutations } from 'vuexfire'
-
-export const mutations = vuexfireMutations
diff --git a/store/sponsors.js b/store/sponsors.js
deleted file mode 100644
index abede1fc..00000000
--- a/store/sponsors.js
+++ /dev/null
@@ -1,12 +0,0 @@
-import { firestoreAction } from 'vuexfire'
-import firestore from '~/utils/firestore'
-
-export const state = () => ({
- all: [],
-})
-
-export const actions = {
- loadAll: firestoreAction((context) =>
- context.bindFirestoreRef('all', firestore.collection('sponsors'))
- ),
-}
diff --git a/tailwind.config.js b/tailwind.config.js
new file mode 100644
index 00000000..c838ae81
--- /dev/null
+++ b/tailwind.config.js
@@ -0,0 +1,104 @@
+/** @type {import('tailwindcss').Config} */
+export default {
+ content: [
+ './components/**/*.{js,vue,ts}',
+ './layouts/**/*.vue',
+ './pages/**/*.vue',
+ './plugins/**/*.{js,ts}',
+ './app.vue',
+ './error.vue',
+ ],
+ safelist: [
+ 'w-1/7',
+ ],
+ theme: {
+ screens: {
+ sm: '576px',
+ md: '768px',
+ lg: '992px',
+ xl: '1200px',
+ },
+ extend: {
+ colors: {
+ attention: '#ff7f50',
+ black: '#22292f',
+ grey: {
+ darkest: '#3d4852',
+ darker: '#606f7b',
+ dark: '#8795a1',
+ DEFAULT: '#b8c2cc',
+ light: '#dae1e7',
+ lighter: '#f1f5f8',
+ lightest: '#f8fafc',
+ },
+ blue: {
+ darkest: '#12283a',
+ darker: '#1c3d5a',
+ dark: '#2779bd',
+ DEFAULT: '#3e79bb',
+ light: '#407cbf',
+ lighter: '#bcdefa',
+ lightest: '#eff8ff',
+ },
+ },
+ fontFamily: {
+ heading: [
+ 'Montserrat',
+ '-apple-system',
+ 'BlinkMacSystemFont',
+ 'Segoe UI',
+ 'Roboto',
+ 'Helvetica Neue',
+ 'Arial',
+ 'sans-serif',
+ ],
+ sans: [
+ '-apple-system',
+ 'BlinkMacSystemFont',
+ 'Segoe UI',
+ 'Roboto',
+ 'Helvetica Neue',
+ 'Arial',
+ 'sans-serif',
+ 'Apple Color Emoji',
+ 'Segoe UI Emoji',
+ 'Segoe UI Symbol',
+ ],
+ serif: [
+ 'Constantia',
+ 'Lucida Bright',
+ 'Lucidabright',
+ 'Lucida Serif',
+ 'Lucida',
+ 'DejaVu Serif',
+ 'Bitstream Vera Serif',
+ 'Liberation Serif',
+ 'Georgia',
+ 'serif',
+ ],
+ mono: [
+ 'Consolas',
+ 'Andale Mono WT',
+ 'Andale Mono',
+ 'Lucida Console',
+ 'Lucida Sans Typewriter',
+ 'DejaVu Sans Mono',
+ 'Bitstream Vera Sans Mono',
+ 'Liberation Mono',
+ 'Nimbus Mono L',
+ 'Monaco',
+ 'Courier New',
+ 'Courier',
+ 'monospace',
+ ],
+ },
+ width: {
+ '1/7': '14.28571%', // For calendar (7-day) view of events
+ },
+ minHeight: {
+ '16': '4rem',
+ },
+ },
+ },
+ plugins: [],
+}
diff --git a/tailwind.js b/tailwind.js
deleted file mode 100644
index 39479482..00000000
--- a/tailwind.js
+++ /dev/null
@@ -1,883 +0,0 @@
-/*
-
-Tailwind - The Utility-First CSS Framework
-
-A project by Adam Wathan (@adamwathan), Jonathan Reinink (@reinink),
-David Hemphill (@davidhemphill) and Steve Schoger (@steveschoger).
-
-Welcome to the Tailwind config file. This is where you can customize
-Tailwind specifically for your project. Don't be intimidated by the
-length of this file. It's really just a big JavaScript object and
-we've done our very best to explain each section.
-
-View the full documentation at https://tailwindcss.com.
-
-
-|-------------------------------------------------------------------------------
-| The default config
-|-------------------------------------------------------------------------------
-|
-| This variable contains the default Tailwind config. You don't have
-| to use it, but it can sometimes be helpful to have available. For
-| example, you may choose to merge your custom configuration
-| values with some of the Tailwind defaults.
-|
-*/
-
-// let defaultConfig = require('tailwindcss/defaultConfig')()
-
-/*
-|-------------------------------------------------------------------------------
-| Colors https://tailwindcss.com/docs/colors
-|-------------------------------------------------------------------------------
-|
-| Here you can specify the colors used in your project. To get you started,
-| we've provided a generous palette of great looking colors that are perfect
-| for prototyping, but don't hesitate to change them for your project. You
-| own these colors, nothing will break if you change everything about them.
-|
-| We've used literal color names ("red", "blue", etc.) for the default
-| palette, but if you'd rather use functional names like "primary" and
-| "secondary", or even a numeric scale like "100" and "200", go for it.
-|
-*/
-
-let colors = {
- transparent: 'transparent',
-
- attention: '#ff7f50',
-
- black: '#22292f',
- 'grey-darkest': '#3d4852',
- 'grey-darker': '#606f7b',
- 'grey-dark': '#8795a1',
- grey: '#b8c2cc',
- 'grey-light': '#dae1e7',
- 'grey-lighter': '#f1f5f8',
- 'grey-lightest': '#f8fafc',
- white: '#ffffff',
-
- 'blue-darkest': '#12283a',
- 'blue-darker': '#1c3d5a',
- 'blue-dark': '#2779bd',
- blue: '#3e79bb',
- 'blue-light': '#407cbf',
- 'blue-lighter': '#bcdefa',
- 'blue-lightest': '#eff8ff',
-}
-
-module.exports = {
- /*
- |-----------------------------------------------------------------------------
- | Colors https://tailwindcss.com/docs/colors
- |-----------------------------------------------------------------------------
- |
- | The color palette defined above is also assigned to the "colors" key of
- | your Tailwind config. This makes it easy to access them in your CSS
- | using Tailwind's config helper. For example:
- |
- | .error { color: config('colors.red') }
- |
- */
-
- colors: colors,
-
- /*
- |-----------------------------------------------------------------------------
- | Screens https://tailwindcss.com/docs/responsive-design
- |-----------------------------------------------------------------------------
- |
- | Screens in Tailwind are translated to CSS media queries. They define the
- | responsive breakpoints for your project. By default Tailwind takes a
- | "mobile first" approach, where each screen size represents a minimum
- | viewport width. Feel free to have as few or as many screens as you
- | want, naming them in whatever way you'd prefer for your project.
- |
- | Tailwind also allows for more complex screen definitions, which can be
- | useful in certain situations. Be sure to see the full responsive
- | documentation for a complete list of options.
- |
- | Class name: .{screen}:{utility}
- |
- */
-
- screens: {
- sm: '576px',
- md: '768px',
- lg: '992px',
- xl: '1200px',
- },
-
- /*
- |-----------------------------------------------------------------------------
- | Fonts https://tailwindcss.com/docs/fonts
- |-----------------------------------------------------------------------------
- |
- | Here is where you define your project's font stack, or font families.
- | Keep in mind that Tailwind doesn't actually load any fonts for you.
- | If you're using custom fonts you'll need to import them prior to
- | defining them here.
- |
- | By default we provide a native font stack that works remarkably well on
- | any device or OS you're using, since it just uses the default fonts
- | provided by the platform.
- |
- | Class name: .font-{name}
- |
- */
-
- fonts: {
- heading: [
- // Montserrat Bold, then Bootstrap native font stack without emojis
- // https://getbootstrap.com/docs/4.3/content/reboot/#native-font-stack
- 'Montserrat',
- '-apple-system',
- 'BlinkMacSystemFont',
- 'Segoe UI',
- 'Roboto',
- 'Helvetica Neue',
- 'Arial',
- 'sans-serif',
- ],
- sans: [
- // Bootstrap native font stack
- // https://getbootstrap.com/docs/4.3/content/reboot/#native-font-stack
- '-apple-system',
- 'BlinkMacSystemFont',
- 'Segoe UI',
- 'Roboto',
- 'Helvetica Neue',
- 'Arial',
- 'sans-serif',
- 'Apple Color Emoji',
- 'Segoe UI Emoji',
- 'Segoe UI Symbol',
- ],
- serif: [
- // Georgia-based font stack
- // https://css-tricks.com/snippets/css/font-stacks/
- 'Constantia',
- 'Lucida Bright',
- 'Lucidabright',
- 'Lucida Serif',
- 'Lucida',
- 'DejaVu Serif',
- 'Bitstream Vera Serif',
- 'Liberation Serif',
- 'Georgia',
- 'serif',
- ],
- mono: [
- // Monospace font stack
- // https://css-tricks.com/snippets/css/font-stacks/
- 'Consolas',
- 'Andale Mono WT',
- 'Andale Mono',
- 'Lucida Console',
- 'Lucida Sans Typewriter',
- 'DejaVu Sans Mono',
- 'Bitstream Vera Sans Mono',
- 'Liberation Mono',
- 'Nimbus Mono L',
- 'Monaco',
- 'Courier New',
- 'Courier',
- 'monospace',
- ],
- },
-
- /*
- |-----------------------------------------------------------------------------
- | Text sizes https://tailwindcss.com/docs/text-sizing
- |-----------------------------------------------------------------------------
- |
- | Here is where you define your text sizes. Name these in whatever way
- | makes the most sense to you. We use size names by default, but
- | you're welcome to use a numeric scale or even something else
- | entirely.
- |
- | By default Tailwind uses the "rem" unit type for most measurements.
- | This allows you to set a root font size which all other sizes are
- | then based on. That said, you are free to use whatever units you
- | prefer, be it rems, ems, pixels or other.
- |
- | Class name: .text-{size}
- |
- */
-
- textSizes: {
- xs: '.75rem', // 12px
- sm: '.875rem', // 14px
- base: '1rem', // 16px
- lg: '1.125rem', // 18px
- xl: '1.25rem', // 20px
- '2xl': '1.5rem', // 24px
- '3xl': '1.875rem', // 30px
- '4xl': '2.25rem', // 36px
- '5xl': '3rem', // 48px
- },
-
- /*
- |-----------------------------------------------------------------------------
- | Font weights https://tailwindcss.com/docs/font-weight
- |-----------------------------------------------------------------------------
- |
- | Here is where you define your font weights. We've provided a list of
- | common font weight names with their respective numeric scale values
- | to get you started. It's unlikely that your project will require
- | all of these, so we recommend removing those you don't need.
- |
- | Class name: .font-{weight}
- |
- */
-
- fontWeights: {
- hairline: 100,
- thin: 200,
- light: 300,
- normal: 400,
- medium: 500,
- semibold: 600,
- bold: 700,
- extrabold: 800,
- black: 900,
- },
-
- /*
- |-----------------------------------------------------------------------------
- | Leading (line height) https://tailwindcss.com/docs/line-height
- |-----------------------------------------------------------------------------
- |
- | Here is where you define your line height values, or as we call
- | them in Tailwind, leadings.
- |
- | Class name: .leading-{size}
- |
- */
-
- leading: {
- none: 1,
- tight: 1.25,
- normal: 1.5,
- loose: 2,
- },
-
- /*
- |-----------------------------------------------------------------------------
- | Tracking (letter spacing) https://tailwindcss.com/docs/letter-spacing
- |-----------------------------------------------------------------------------
- |
- | Here is where you define your letter spacing values, or as we call
- | them in Tailwind, tracking.
- |
- | Class name: .tracking-{size}
- |
- */
-
- tracking: {
- tight: '-0.05em',
- normal: '0',
- wide: '0.05em',
- },
-
- /*
- |-----------------------------------------------------------------------------
- | Text colors https://tailwindcss.com/docs/text-color
- |-----------------------------------------------------------------------------
- |
- | Here is where you define your text colors. By default these use the
- | color palette we defined above, however you're welcome to set these
- | independently if that makes sense for your project.
- |
- | Class name: .text-{color}
- |
- */
-
- textColors: colors,
-
- /*
- |-----------------------------------------------------------------------------
- | Background colors https://tailwindcss.com/docs/background-color
- |-----------------------------------------------------------------------------
- |
- | Here is where you define your background colors. By default these use
- | the color palette we defined above, however you're welcome to set
- | these independently if that makes sense for your project.
- |
- | Class name: .bg-{color}
- |
- */
-
- backgroundColors: colors,
-
- /*
- |-----------------------------------------------------------------------------
- | Background sizes https://tailwindcss.com/docs/background-size
- |-----------------------------------------------------------------------------
- |
- | Here is where you define your background sizes. We provide some common
- | values that are useful in most projects, but feel free to add other sizes
- | that are specific to your project here as well.
- |
- | Class name: .bg-{size}
- |
- */
-
- backgroundSize: {
- auto: 'auto',
- cover: 'cover',
- contain: 'contain',
- },
-
- /*
- |-----------------------------------------------------------------------------
- | Border widths https://tailwindcss.com/docs/border-width
- |-----------------------------------------------------------------------------
- |
- | Here is where you define your border widths. Take note that border
- | widths require a special "default" value set as well. This is the
- | width that will be used when you do not specify a border width.
- |
- | Class name: .border{-side?}{-width?}
- |
- */
-
- borderWidths: {
- default: '1px',
- 0: '0',
- 2: '2px',
- 4: '4px',
- 8: '8px',
- },
-
- /*
- |-----------------------------------------------------------------------------
- | Border colors https://tailwindcss.com/docs/border-color
- |-----------------------------------------------------------------------------
- |
- | Here is where you define your border colors. By default these use the
- | color palette we defined above, however you're welcome to set these
- | independently if that makes sense for your project.
- |
- | Take note that border colors require a special "default" value set
- | as well. This is the color that will be used when you do not
- | specify a border color.
- |
- | Class name: .border-{color}
- |
- */
-
- borderColors: global.Object.assign({ default: colors['grey-light'] }, colors),
-
- /*
- |-----------------------------------------------------------------------------
- | Border radius https://tailwindcss.com/docs/border-radius
- |-----------------------------------------------------------------------------
- |
- | Here is where you define your border radius values. If a `default` radius
- | is provided, it will be made available as the non-suffixed `.rounded`
- | utility.
- |
- | If your scale includes a `0` value to reset already rounded corners, it's
- | a good idea to put it first so other values are able to override it.
- |
- | Class name: .rounded{-side?}{-size?}
- |
- */
-
- borderRadius: {
- none: '0',
- sm: '.125rem',
- default: '.25rem',
- lg: '.5rem',
- full: '9999px',
- },
-
- /*
- |-----------------------------------------------------------------------------
- | Width https://tailwindcss.com/docs/width
- |-----------------------------------------------------------------------------
- |
- | Here is where you define your width utility sizes. These can be
- | percentage based, pixels, rems, or any other units. By default
- | we provide a sensible rem based numeric scale, a percentage
- | based fraction scale, plus some other common use-cases. You
- | can, of course, modify these values as needed.
- |
- |
- | It's also worth mentioning that Tailwind automatically escapes
- | invalid CSS class name characters, which allows you to have
- | awesome classes like .w-2/3.
- |
- | Class name: .w-{size}
- |
- */
-
- width: {
- auto: 'auto',
- px: '1px',
- 1: '0.25rem',
- 2: '0.5rem',
- 3: '0.75rem',
- 4: '1rem',
- 5: '1.25rem',
- 6: '1.5rem',
- 8: '2rem',
- 10: '2.5rem',
- 12: '3rem',
- 16: '4rem',
- 24: '6rem',
- 32: '8rem',
- 48: '12rem',
- 64: '16rem',
- '1/2': '50%',
- '1/3': '33.33333%',
- '2/3': '66.66667%',
- '1/4': '25%',
- '3/4': '75%',
- '1/5': '20%',
- '2/5': '40%',
- '3/5': '60%',
- '4/5': '80%',
- '1/7': '14.28571%', // For calendar (7-day) view of events
- full: '100%',
- screen: '100vw',
- },
-
- /*
- |-----------------------------------------------------------------------------
- | Height https://tailwindcss.com/docs/height
- |-----------------------------------------------------------------------------
- |
- | Here is where you define your height utility sizes. These can be
- | percentage based, pixels, rems, or any other units. By default
- | we provide a sensible rem based numeric scale plus some other
- | common use-cases. You can, of course, modify these values as
- | needed.
- |
- | Class name: .h-{size}
- |
- */
-
- height: {
- auto: 'auto',
- px: '1px',
- 1: '0.25rem',
- 2: '0.5rem',
- 3: '0.75rem',
- 4: '1rem',
- 5: '1.25rem',
- 6: '1.5rem',
- 8: '2rem',
- 10: '2.5rem',
- 12: '3rem',
- 16: '4rem',
- 24: '6rem',
- 32: '8rem',
- 40: '10rem',
- 48: '12rem',
- 64: '16rem',
- full: '100%',
- screen: '100vh',
- },
-
- /*
- |-----------------------------------------------------------------------------
- | Minimum width https://tailwindcss.com/docs/min-width
- |-----------------------------------------------------------------------------
- |
- | Here is where you define your minimum width utility sizes. These can
- | be percentage based, pixels, rems, or any other units. We provide a
- | couple common use-cases by default. You can, of course, modify
- | these values as needed.
- |
- | Class name: .min-w-{size}
- |
- */
-
- minWidth: {
- 0: '0',
- full: '100%',
- },
-
- /*
- |-----------------------------------------------------------------------------
- | Minimum height https://tailwindcss.com/docs/min-height
- |-----------------------------------------------------------------------------
- |
- | Here is where you define your minimum height utility sizes. These can
- | be percentage based, pixels, rems, or any other units. We provide a
- | few common use-cases by default. You can, of course, modify these
- | values as needed.
- |
- | Class name: .min-h-{size}
- |
- */
-
- minHeight: {
- 0: '0',
- 16: '4rem',
- full: '100%',
- screen: '100vh',
- },
-
- /*
- |-----------------------------------------------------------------------------
- | Maximum width https://tailwindcss.com/docs/max-width
- |-----------------------------------------------------------------------------
- |
- | Here is where you define your maximum width utility sizes. These can
- | be percentage based, pixels, rems, or any other units. By default
- | we provide a sensible rem based scale and a "full width" size,
- | which is basically a reset utility. You can, of course,
- | modify these values as needed.
- |
- | Class name: .max-w-{size}
- |
- */
-
- maxWidth: {
- sm: '30rem',
- md: '40rem',
- lg: '50rem',
- xl: '60rem',
- '2xl': '70rem',
- '3xl': '80rem',
- '4xl': '90rem',
- '5xl': '100rem',
- full: '100%',
- },
-
- /*
- |-----------------------------------------------------------------------------
- | Maximum height https://tailwindcss.com/docs/max-height
- |-----------------------------------------------------------------------------
- |
- | Here is where you define your maximum height utility sizes. These can
- | be percentage based, pixels, rems, or any other units. We provide a
- | couple common use-cases by default. You can, of course, modify
- | these values as needed.
- |
- | Class name: .max-h-{size}
- |
- */
-
- maxHeight: {
- full: '100%',
- screen: '100vh',
- },
-
- /*
- |-----------------------------------------------------------------------------
- | Padding https://tailwindcss.com/docs/padding
- |-----------------------------------------------------------------------------
- |
- | Here is where you define your padding utility sizes. These can be
- | percentage based, pixels, rems, or any other units. By default we
- | provide a sensible rem based numeric scale plus a couple other
- | common use-cases like "1px". You can, of course, modify these
- | values as needed.
- |
- | Class name: .p{side?}-{size}
- |
- */
-
- padding: {
- px: '1px',
- 0: '0',
- 1: '0.25rem',
- 2: '0.5rem',
- 3: '0.75rem',
- 4: '1rem',
- 5: '1.25rem',
- 6: '1.5rem',
- 8: '2rem',
- 10: '2.5rem',
- 12: '3rem',
- 16: '4rem',
- 20: '5rem',
- 24: '6rem',
- 32: '8rem',
- 64: '16rem',
- },
-
- /*
- |-----------------------------------------------------------------------------
- | Margin https://tailwindcss.com/docs/margin
- |-----------------------------------------------------------------------------
- |
- | Here is where you define your margin utility sizes. These can be
- | percentage based, pixels, rems, or any other units. By default we
- | provide a sensible rem based numeric scale plus a couple other
- | common use-cases like "1px". You can, of course, modify these
- | values as needed.
- |
- | Class name: .m{side?}-{size}
- |
- */
-
- margin: {
- auto: 'auto',
- px: '1px',
- 0: '0',
- 1: '0.25rem',
- 2: '0.5rem',
- 3: '0.75rem',
- 4: '1rem',
- 5: '1.25rem',
- 6: '1.5rem',
- 8: '2rem',
- 10: '2.5rem',
- 12: '3rem',
- 16: '4rem',
- 20: '5rem',
- 24: '6rem',
- 32: '8rem',
- },
-
- /*
- |-----------------------------------------------------------------------------
- | Negative margin https://tailwindcss.com/docs/negative-margin
- |-----------------------------------------------------------------------------
- |
- | Here is where you define your negative margin utility sizes. These can
- | be percentage based, pixels, rems, or any other units. By default we
- | provide matching values to the padding scale since these utilities
- | generally get used together. You can, of course, modify these
- | values as needed.
- |
- | Class name: .-m{side?}-{size}
- |
- */
-
- negativeMargin: {
- px: '1px',
- 0: '0',
- 1: '0.25rem',
- 2: '0.5rem',
- 3: '0.75rem',
- 4: '1rem',
- 5: '1.25rem',
- 6: '1.5rem',
- 8: '2rem',
- 10: '2.5rem',
- 12: '3rem',
- 16: '4rem',
- 20: '5rem',
- 24: '6rem',
- 32: '8rem',
- 48: '12rem',
- 64: '16rem',
- },
-
- /*
- |-----------------------------------------------------------------------------
- | Shadows https://tailwindcss.com/docs/shadows
- |-----------------------------------------------------------------------------
- |
- | Here is where you define your shadow utilities. As you can see from
- | the defaults we provide, it's possible to apply multiple shadows
- | per utility using comma separation.
- |
- | If a `default` shadow is provided, it will be made available as the non-
- | suffixed `.shadow` utility.
- |
- | Class name: .shadow-{size?}
- |
- */
-
- shadows: {
- default: '0 2px 4px 0 rgba(0,0,0,0.10)',
- md: '0 4px 8px 0 rgba(0,0,0,0.12), 0 2px 4px 0 rgba(0,0,0,0.08)',
- lg: '0 15px 30px 0 rgba(0,0,0,0.11), 0 5px 15px 0 rgba(0,0,0,0.08)',
- inner: 'inset 0 2px 4px 0 rgba(0,0,0,0.06)',
- outline: '0 0 0 3px rgba(52,144,220,0.5)',
- none: 'none',
- },
-
- /*
- |-----------------------------------------------------------------------------
- | Z-index https://tailwindcss.com/docs/z-index
- |-----------------------------------------------------------------------------
- |
- | Here is where you define your z-index utility values. By default we
- | provide a sensible numeric scale. You can, of course, modify these
- | values as needed.
- |
- | Class name: .z-{index}
- |
- */
-
- zIndex: {
- auto: 'auto',
- 0: 0,
- 10: 10,
- 20: 20,
- 30: 30,
- 40: 40,
- 50: 50,
- },
-
- /*
- |-----------------------------------------------------------------------------
- | Opacity https://tailwindcss.com/docs/opacity
- |-----------------------------------------------------------------------------
- |
- | Here is where you define your opacity utility values. By default we
- | provide a sensible numeric scale. You can, of course, modify these
- | values as needed.
- |
- | Class name: .opacity-{name}
- |
- */
-
- opacity: {
- 0: '0',
- 25: '.25',
- 50: '.5',
- 75: '.75',
- 100: '1',
- },
-
- /*
- |-----------------------------------------------------------------------------
- | SVG fill https://tailwindcss.com/docs/svg
- |-----------------------------------------------------------------------------
- |
- | Here is where you define your SVG fill colors. By default we just provide
- | `fill-current` which sets the fill to the current text color. This lets you
- | specify a fill color using existing text color utilities and helps keep the
- | generated CSS file size down.
- |
- | Class name: .fill-{name}
- |
- */
-
- svgFill: {
- current: 'currentColor',
- },
-
- /*
- |-----------------------------------------------------------------------------
- | SVG stroke https://tailwindcss.com/docs/svg
- |-----------------------------------------------------------------------------
- |
- | Here is where you define your SVG stroke colors. By default we just provide
- | `stroke-current` which sets the stroke to the current text color. This lets
- | you specify a stroke color using existing text color utilities and helps
- | keep the generated CSS file size down.
- |
- | Class name: .stroke-{name}
- |
- */
-
- svgStroke: {
- current: 'currentColor',
- },
-
- /*
- |-----------------------------------------------------------------------------
- | Modules https://tailwindcss.com/docs/configuration#modules
- |-----------------------------------------------------------------------------
- |
- | Here is where you control which modules are generated and what variants are
- | generated for each of those modules.
- |
- | Currently supported variants:
- | - responsive
- | - hover
- | - focus
- | - active
- | - group-hover
- |
- | To disable a module completely, use `false` instead of an array.
- |
- */
-
- modules: {
- appearance: [],
- backgroundAttachment: [],
- backgroundColors: ['hover', 'focus'],
- backgroundPosition: [],
- backgroundRepeat: [],
- backgroundSize: [],
- borderCollapse: [],
- borderColors: ['hover', 'focus'],
- borderRadius: [],
- borderStyle: [],
- borderWidths: [],
- cursor: [],
- display: ['responsive'],
- flexbox: ['responsive'],
- float: [],
- fonts: [],
- fontWeights: ['hover', 'focus'],
- height: [],
- leading: [],
- lists: [],
- margin: ['responsive'],
- maxHeight: [],
- maxWidth: ['responsive'],
- minHeight: [],
- minWidth: [],
- negativeMargin: ['responsive'],
- opacity: [],
- outline: ['focus'],
- overflow: [],
- padding: ['responsive'],
- pointerEvents: [],
- position: [],
- resize: [],
- shadows: ['active', 'hover', 'focus'],
- svgFill: [],
- svgStroke: [],
- textAlign: [],
- textColors: ['hover', 'focus'],
- textSizes: [],
- textStyle: ['hover', 'focus'],
- tracking: [],
- userSelect: [],
- verticalAlign: [],
- visibility: [],
- whitespace: [],
- width: ['responsive'],
- zIndex: [],
- },
-
- /*
- |-----------------------------------------------------------------------------
- | Plugins https://tailwindcss.com/docs/plugins
- |-----------------------------------------------------------------------------
- |
- | Here is where you can register any plugins you'd like to use in your
- | project. Tailwind's built-in `container` plugin is enabled by default to
- | give you a Bootstrap-style responsive container component out of the box.
- |
- | Be sure to view the complete plugin documentation to learn more about how
- | the plugin system works.
- |
- */
-
- plugins: [
- require('tailwindcss/plugins/container')({
- // center: true,
- // padding: '1rem',
- }),
- ],
-
- /*
- |-----------------------------------------------------------------------------
- | Advanced Options https://tailwindcss.com/docs/configuration#options
- |-----------------------------------------------------------------------------
- |
- | Here is where you can tweak advanced configuration options. We recommend
- | leaving these options alone unless you absolutely need to change them.
- |
- */
-
- options: {
- prefix: '',
- important: false,
- separator: ':',
- },
-}
diff --git a/tests/ui-check.spec.js b/tests/ui-check.spec.js
new file mode 100644
index 00000000..c6f06517
--- /dev/null
+++ b/tests/ui-check.spec.js
@@ -0,0 +1,66 @@
+import { test, expect } from '@playwright/test';
+
+test('Check Lansing Codes homepage UI', async ({ page }) => {
+ // Go to the homepage
+ await page.goto('http://localhost:3001');
+
+ // Wait for page to load
+ await page.waitForLoadState('networkidle');
+
+ // Take a full page screenshot
+ await page.screenshot({
+ path: 'homepage-full.png',
+ fullPage: true
+ });
+
+ // Check for main heading
+ const heading = page.getByRole('heading', { name: 'Lansing Codes', level: 1 });
+ await expect(heading).toBeVisible();
+
+ // Check for navigation links
+ const slackLink = page.getByRole('link', { name: /slack/i });
+ const eventsLink = page.getByRole('link', { name: /events/i });
+ const groupsLink = page.getByRole('link', { name: /groups/i });
+ const resourcesLink = page.getByRole('link', { name: /resources/i });
+ const sponsorsLink = page.getByRole('link', { name: /sponsors/i });
+ const newsletterLink = page.getByRole('link', { name: /newsletter/i });
+
+ await expect(slackLink).toBeVisible();
+ await expect(eventsLink).toBeVisible();
+ await expect(groupsLink).toBeVisible();
+ await expect(resourcesLink).toBeVisible();
+ await expect(sponsorsLink).toBeVisible();
+ await expect(newsletterLink).toBeVisible();
+
+ // Check for sections
+ await expect(page.locator('#events')).toBeInViewport();
+ await expect(page.locator('#meetups')).toBeVisible();
+ await expect(page.locator('#sponsors')).toBeVisible();
+
+ // Log any console errors
+ const errors = [];
+ page.on('console', msg => {
+ if (msg.type() === 'error') {
+ errors.push(msg.text());
+ }
+ });
+
+ // Check for JavaScript errors
+ page.on('pageerror', error => {
+ console.log('Page Error:', error.message);
+ });
+
+ // Output console errors if any
+ if (errors.length > 0) {
+ console.log('Console Errors:', errors);
+ }
+
+ // Check if FontAwesome icons are loading
+ const icons = await page.locator('svg[data-icon]').count();
+ console.log(`Found ${icons} FontAwesome icons`);
+
+ // Take screenshots of specific sections
+ await page.locator('#welcome').screenshot({ path: 'welcome-section.png' });
+ await page.locator('#meetups').screenshot({ path: 'meetups-section.png' });
+ await page.locator('#sponsors').screenshot({ path: 'sponsors-section.png' });
+});
diff --git a/utils/clean-event-description.js b/utils/clean-event-description.js
index 00c30795..a998912e 100644
--- a/utils/clean-event-description.js
+++ b/utils/clean-event-description.js
@@ -1,4 +1,4 @@
-export default (description) => {
+export default description => {
// Trim whitespace
let newDescription = description.trim()
// Remove elipsis at end of description
diff --git a/utils/firestore.js b/utils/firestore.js
index c18970f9..a082760a 100644
--- a/utils/firestore.js
+++ b/utils/firestore.js
@@ -1,6 +1,17 @@
-import firebase from '@firebase/app'
-import '@firebase/firestore'
+import { initializeApp } from 'firebase/app'
+import { getFirestore } from 'firebase/firestore'
-const firebaseApp = firebase.initializeApp(process.env.firebaseWebConfig)
+const firebaseConfig = {
+ apiKey: 'AIzaSyCMw8mZ1D1GAYpeotAqVCaYAMtn3URVOok',
+ authDomain: 'lansing-codes.firebaseapp.com',
+ databaseURL: 'https://lansing-codes.firebaseio.com',
+ projectId: 'lansing-codes',
+ storageBucket: 'lansing-codes.appspot.com',
+ messagingSenderId: '647280182517',
+ appId: '1:647280182517:web:779f72d0b90c0dd4',
+}
-export default firebaseApp.firestore()
+const firebaseApp = initializeApp(firebaseConfig)
+export const db = getFirestore(firebaseApp)
+
+export default db
diff --git a/utils/format-readable-date-time.js b/utils/format-readable-date-time.js
index 764f9351..875ac247 100644
--- a/utils/format-readable-date-time.js
+++ b/utils/format-readable-date-time.js
@@ -1,3 +1,3 @@
import { format } from 'date-fns'
-export default (time) => format(time, 'dddd, MMMM D [at] h:mm aa')
+export default time => format(time, 'dddd, MMMM d \'at\' h:mm aa')
diff --git a/utils/group-for-event.js b/utils/group-for-event.js
index bf848353..b8d21008 100644
--- a/utils/group-for-event.js
+++ b/utils/group-for-event.js
@@ -1,2 +1 @@
-export default (event, groups) =>
- groups.find((group) => group.id === event.group)
+export default (event, groups) => groups.find(group => group.id === event.group)
diff --git a/utils/simplified-name.js b/utils/simplified-name.js
index 6aa436e6..8f32b8aa 100644
--- a/utils/simplified-name.js
+++ b/utils/simplified-name.js
@@ -1,2 +1,2 @@
// Removes non-alphanumeric characters and makes it lowercase
-export default (name) => name.toLowerCase().replace(/[^a-z0-9]/g, '')
+export default name => name.toLowerCase().replace(/[^a-z0-9]/g, '')