A Twitter
and Borderlands 3
inspired social media platform dedicated to discussing in-game loot drops
between users and players.
Initially planned as an interactive loot table for the video game Borderlands 3, BL3 Companion App
is a hybrid loot-tracker-social-media-app
dedicated to sharing and discussing in-game loot drops
.
Much like how Twitter
enables users to compose and post Tweets
, BL3 Companion
enables users to compose and post Loot Drops
; each of which pertain to a particular loot item
from the game. Posted Loot
will appear in the feed
of their followers
and the loot drops
posted by other users they follow
in the same way it does on Twitter
.
Users can like
and comment
on other users Loot Drops
and follow
other users much like you can on Twitter
.
A list of recent changes and/or modifications...
If you would like to see a wireframe test of the updated UI, please checkout:
- BL3 Companion App - Test Server
- This is still under development, it is a demonstration of the new site's UI responsiveness and controls.
Please checkout the updated repo for more information. Thanks!
-
As per MDN:
Cross-Origin-Embedder-Policy:
The HTTP Cross-Origin-Embedder-Policy (COEP) response header prevents a document from loading any cross-origin resources that don't explicitly grant the document permission (using CORP or CORS).
Cross-Origin-Embedder-Policy: unsafe-none | require-corp
...
Avoiding COEP blockage with CORS:
If you enable COEP using require-corp and have a cross origin resource that needs to be loaded, it needs to support CORS and you need to explicitly mark the resource as loadable from another origin to avoid blockage from COEP. For example, you can use the crossorigin attribute for this image from a third-party site:
<img src="https://thirdparty.com/img.png" crossorigin />
-
Window.sessionStorage
; as per MDN:The read-only
sessionStorage
property accesses a sessionStorage
object for the current origin.sessionStorage
is similar tolocalStorage
; the difference is that while data inlocalStorage
doesn't expire, data insessionStorage
is cleared when the page session ends.As it pertains to the
app
; we keep a copy of theloot
from theRedux
store insessionStorage
to optimize loading times for thefeed
thus enabling us to free up additional resources within ourSQL-Alchemy
server. After the initial download of the session from the server, ourapp
focuses on delivering updates to and from the server with respect to each individual client user's state.Should the user refresh the page, logout and immediately log back in, or navigate away and then back to the site, the entire
app
need not be reloaded from the database. If we find a saved state withinsessionStorage
, theapp
loads from that last known state, then checks to see if additional updates are required.Changes made to the state of the
app
at any given time are pushed to both theRedux
store andsessionStorage
. This is accomplished inReact
via theuseEffect
hook to inquire whether an update is necessary. An update will be necessary if a user has:- Created a new
Loot Drop
, - Updated a previous
Loot Drop
, - Created a new
comment
, - Replied to a previous
comment
, - Clicked
Like
on aLoot Drop
, Followed
another user for the first time,Unfollowed
a previous user
Updates will be sent to and parsed by
React
, allowing the relevant components to be rendered or re-rendered as needed. The incoming updates are added to theRedux
store and then compared to oursessionStorage
This is done to minimize unecessaryasynchronous
JavaSript
calls to oursessionStorage
.//Example use case from within our main React <App /> component. const App = () => { const dispatch = useDispatch(); const { userId, userName, loggedOut } = useSelector((state) => state.auth); const { lootDrops, newLootAvailable } = useSelector( (state) => state.lootDrops ); const lootStorage = window.sessionStorage; useEffect(() => { let lootStored = lootStorage.getItem("lootStored"); if (JSON.parse(lootStored)) { let totalLootDrops = lootStorage.getItem("totalLootDrops"); totalLootDrops = JSON.parse(totalLootDrops); let loot = []; for (let i = 0; i < totalLootDrops; i++) { let lootItem = lootStorage.getItem(`lootDrop${i}`); loot.push(JSON.parse(lootItem)); } return dispatch({ type: LOOT_DROPS, lootDrops: loot }); } if (newLootAvailable) { lootStorage.setItem("newLootDropAvailable", JSON.stringify(false)); return dispatch(getLootDrops(userId)); } }, [userId, lootDrops, dispatch, lootStorage, newLootAvailable]); return ( //...rest of code omitted for brevity... ); }; export default App;
- Created a new
Potential features and/or changes coming in the future...
-
We are happy to announce that a major update is currently underway! We hope that these changes bring:
- A better user experience,
- Improved functionality,
- A more maintainable code base on the backend...
-
Complete overhaul of styling and layout using custom
Bulma
templates, allowing for better responsivness and rendering on multiple viewports.(ie: fullHD, standard desktop, tablets, and mobile devices.)
-
New landing page with
login
/signup
menus. -
Better UI for generating
loot drops
. -
Sidenav with
<BrowserRouter />
androute configs
. -
The user will be able to select a new avatar from a predefined list of choices
-
A list of all possible
loot items
that can be found in game and references to them generated from FANDOM wikia.We would like the user to be able to browse all in-game items and view
loot drops
relevant to the items they browse. This will enable users to find other users and connect them to each other. -
Saving State on
Window.closed
events which will enablesessionStorage
to persist between closing and reopening the browser.We may want to implement saving the last known state of the
app
tolocalStorage
just in case the browser is closed and them immediately reopened. This will optimize cases where a user may close and reopen a within a specified range of time. If the state is beyond that specified time, cleared, or otherwise not available, theapp
will need to be loaded as normal. -
Allow the user to upload a custom avatar image and background for their profile.
We would love it if users could upload their own images for avatars and background images. These would be hosted on our AWS bucket and would require our database to handle assignment to users and CORS authentication.
Flowchart diagram of the app
's technology stack...
Backend:
PostgreSQL
DatabaseFlask-SQLAlchemy
API
Frontend:
React.js
Redux
(state management)JavaScript
for handlingsessionStorage
Sass
for rendered styles.