let app = {
title: 'something about 🚴♀️📚🌎☕️ ?',
idea: 'Look 👇 for the 🦄',
missionStatement: `
The first cool social media app that's good for the goddamn world. Or more specifically, an Instagram/Strava kinda thing that financially benefits local businesses/bookstores, incentivizes healthy/carbon-neutral travel within your community, and encourages the beautiful act of selecting a book for a friend.
`
}
- Create a profile.
- Stuff like:
{interests,fav_book,fav_bike,profile_pic_url}
- Stuff like:
- Friend and follow other users who've opted into a non-default social version of the app that is only available after a user has created three valid posts.
- Create a post.
- A post is an instance of a user documenting, with metadata/photos/text/mapped-routes:
- Adventuring to a local, independent book store.
- Something cool, like Birchbark Books.
- Buying a book at a local, independent book store.
- Something cool, like The Shadow of Sirius.
- Adventuring from the local, independent book store to the gift book's destination.
- Optionally stopping at a local, independent cafe.
- Something cool, like Prairie Sky Breads.
- Adventuring to a local, independent book store.
- A post is an instance of a user documenting, with metadata/photos/text/mapped-routes:
- Comment on posts.
- Give props to posts.
- Categories of props:
- Cool book!
- Cool book store!
- Cool cafe!
- Cool mode of transportation!
- Cool route!
- Categories of props:
- Share posts.
- Browse a monthly, editorially curated selection of five awesome posts.
- Have a convenient and enjoyable way to view metadata for posts, in order to curate public-facing content.
- The only profit motives are, and can only ever be:
- Nudging society toward carbon-neutral transportation methods being the norm.
- Financially benefitting local, small businesses.
This is an exploration of building a React/Express app using newer tools/libraries/APIs. Eventually it'll be a multi-user blog with posts, comments, and likes. Maybe there will be some flexbox, because flexbox is all I really know. 🙂
Things that are different from the post-Hooks Prime stack:
vite
instead ofCRA
.react-router
v6 instead of v5.express-session
instead ofpassport
.Context
instead ofRedux/Redux-Saga
.
- Create a
blog
database.- Or, create a database and name it
blizzard_kangaroo
for all I care. (You'll just need to make thedatabase
property also beblizzard_kangaroo
over in./server/modules/pool.cjs
).
- Or, create a database and name it
- Run the queries from
/db/schema.sql
. - Run the queries from
/db/seed.sql
. npm install
.npm run server
.npm run client
.- Enjoy using this highly complex web application!
AKA: Prime
My ongoing/condensed notes on how this approach differs from our current stack/curriculum.
- The end. It's just awesome. ⚡️
- Weird thing though, any files that aren't using ESM import/export syntax need to use the
.cjs
file extension. (I really dig the explictness of that.)
<NavLink>
is cool.- It has extra special powers if following a certain data querying paradigm:
- Otherwise, the difference between Link and NavLink is that NavLink, by default, has an 'active' CSS class applied to it when a user is "at" that route.
- There's a cool new paradigm that uses an
<Outlet/>
wrapper component. It sounds like this is how Remix works, and v6 slurped up a good idea that provides a good dev experience.- Docs for the
<Outlet />
component: - Check out line 38 here. Everything inside the
'<Layout />
component is nested in both:- The React Router path.
- The React component tree.
- Kinda neat, but a different approach for sure.
- Docs for the
- I haven't gotten all the way through this, but it's worth reading for some context on what React Router is exploring:
- I chose to use cookies/sessions rather than JWT.
express-session
is a very straightforward and less abstract replacement forpassport
.- The top answer to this question is why I went with cookies/sessions:
- I'd be very excited to teach about what happens inside
sessionMiddleware.cjs
, especially getting students to understand the importance of thesameSite: true, httpOnly: true
cookie options. (This feels just as important as teaching about password hashing.) - I used
bcrypt
for the two util functions inpassword.cjs
. Are we still thinking we want to switch toargon2
?
Notes on Redux/Redux-Saga vs Context:
- There is still a Provider component.
- For each context you choose to create, you also create a custom wrapper component to act as the context's Provider.
- Instead of reducers and Saga functions housed in the Redux store, we use React state and JS functions that the context Provider exposes.
- Instead of useSelector to read global Redux state and useDispatch to yell at global Saga functions, any of the context Provider's children can access context state and functions via a useBlahContext hook.
When to use Context?
- Context should not be thought of as pure replacement of Redux:
- If used to hold ALL of an application's global state, it'd causes lots of unnecessary/performance-decreasing re-renders.
- I am not sure why, but multiple resources indicated this.
- If used to hold ALL of an application's global state, it'd causes lots of unnecessary/performance-decreasing re-renders.
- The use case for Context is if you need to have a globally available piece of state that doesn't change often. Stuff like themes, locales, and user status.
- It is a great solution for this small handful of use cases.
Overview of how Context works in this app:
- Check out how the
useAuthContext
hook gets used in the four filesimport
it: - Check out the
AuthContext.jsx
file. I left verbose comments that explain how it works, and especially how it high-level compares/contrasts to a Redux/Redux-Sagas implementation. This all feels very teachable to me. And valuable to teach. 🙂
- What adds mental overhead?
- Only thing I've noticed so far is having to make choices about my own organizational structure.
- What decreases mental overhead?
- So far, it's a win to not have to deal with the so much extra file-making and indirection. I feel a bit "closer" to what I'm trying to accomplish.
- Extra tidbits:
- Building has been straightforward, and it's nice to know that I have
/src/contexts
waiting for me in the event of some kind of complicated state situation arising. It feels like a safety valve. I figured I'd prefer the straightforwardness of vanilla React, but I'm surprised at the this-feels-nice-ness of having said safety valve available.
- Building has been straightforward, and it's nice to know that I have
- Post and PostPreviewItem both need conditionally rendered:
- Private/public toggle. (✅PostPreviewItem)
- Edit button.
- Delete button.
- Likes for posts/comments.
- Lots of duplication of this lil' friend in posts.router:
if (isNaN(Number(req.params.id))) {
res.sendStatus(400)
return
}
- I guess use some kind of MUI-ish component library to make this more closely resemble a typical student solo project? 🤷
- Add some kind of API integration with Google Maps, just to start figuring out what you'll need to know to build out the Books, Bikes stuff.