{"id":27338172,"url":"https://github.com/jenbrissman/followspot","last_synced_at":"2025-04-12T15:25:53.211Z","repository":{"id":45011411,"uuid":"337856669","full_name":"jenbrissman/FollowSpot","owner":"jenbrissman","description":"FollowSpot is a comprehensive audition tracking fullstack web application for entertainment industry professionals. This app allows users to store information/media for all of their auditions while also compiling data and displaying statistics to help track progress. Demo Video: https://youtu.be/AkxajodTJZs | Deployed: https://followspot.herokuapp.com/","archived":false,"fork":false,"pushed_at":"2021-12-08T17:09:29.000Z","size":74081,"stargazers_count":9,"open_issues_count":0,"forks_count":5,"subscribers_count":1,"default_branch":"master","last_synced_at":"2023-07-01T02:44:58.402Z","etag":null,"topics":["auditions","bootstrap","cards","chartjs","cloudinary","cloudinary-api","css","flask","google","google-maps-api","html","industry","jinja","postgresql","python","python3","sqalchemy","sql","sqlalchemy","twilio-api"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/jenbrissman.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2021-02-10T21:18:45.000Z","updated_at":"2023-07-01T02:44:58.403Z","dependencies_parsed_at":"2022-08-25T14:51:47.025Z","dependency_job_id":null,"html_url":"https://github.com/jenbrissman/FollowSpot","commit_stats":null,"previous_names":[],"tags_count":null,"template":null,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jenbrissman%2FFollowSpot","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jenbrissman%2FFollowSpot/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jenbrissman%2FFollowSpot/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jenbrissman%2FFollowSpot/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/jenbrissman","download_url":"https://codeload.github.com/jenbrissman/FollowSpot/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248588031,"owners_count":21129323,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["auditions","bootstrap","cards","chartjs","cloudinary","cloudinary-api","css","flask","google","google-maps-api","html","industry","jinja","postgresql","python","python3","sqalchemy","sql","sqlalchemy","twilio-api"],"created_at":"2025-04-12T15:25:52.551Z","updated_at":"2025-04-12T15:25:53.198Z","avatar_url":"https://github.com/jenbrissman.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"![followSpot](static/img/SmallLogo.png \"followSpot\")\n\nby [Jen Brissman](https://www.linkedin.com/in/jenbrissman/) | [brissman514@gmail.com](mailto:brissman514@gmail.com?subject=[GitHub]%20FollowSpot) | [Watch the demo!](https://www.youtube.com/watch?v=AkxajodTJZs\u0026t=23s)\n\n![DemoGIF](static/img/Demo.GIF \"DemoGIF\")\n\nTable of Contents\n------\n- [Tech Stack](#Tech)\n- [About](#About)\n- [Testing](#Testing)\n- [Features](#Features)\n- [Looking Ahead](#Future)\n- [Meet the Developer](#Meet)\n- [Acknowledgments](#Acknowledgments)\n- [Install](#Install)\n\n## \u003ca name=\"#Tech\"\u003e\u003c/a\u003eTech Stack\n\n- **Frontend**: JavaScript | jQuery | HTML5 | CSS | Bootstrap\n- **Backend**: Python3 | Flask | SQLAlchemy | Jinja2\n- **APIs**: Cloudinary | Twilio | GoogleMaps | Chart.js\n- **Database**: PostgreSQL\n\n## \u003ca name=\"#About\"\u003e\u003c/a\u003eAbout\n\nFollowSpot is a comprehensive audition tracking full stack web application for entertainment industry professionals. This application allows users to store information and media for all of their auditions while also compiling data and displaying statistics to help track their progress.\n\n## \u003ca name=\"#Testing\"\u003e\u003c/a\u003eTesting\n\nFor my tests, I used [Coverage.py](https://coverage.readthedocs.io/en/coverage-5.5/) as it allows you to see your test coverage.\n\n1. To run coverage, run this command:\n```shell\n$ coverage run -m unittest discover.\n```\n\n2. To see the coverage report, run: \n```shell\n$ coverage report -m.\n```\n\n## \u003ca name=\"#Features\"\u003e\u003c/a\u003eFeatures\n\n## \u003ca name=\"#Login\"\u003e\u003c/a\u003eLogin and Registration\nThe user will create a personal account to store all of their audition information and materials. I have integrated the Twilio API to send the user an SMS message confirming their connection to the app.\n\n![Login](static/img/Login.GIF)\n\n## \u003ca name=\"#Timeline\"\u003e\u003c/a\u003eAudition Timeline\nTo develop a responsive and user friendly interface - I styled FollowSpot with Bootstrap and my own custom CSS. I provide the user with a collection of thoughtfully designed cards which contain all of the information about a specific audition. My design uses Jinja templating to dynamically load the data onto individual cards, which I've sorted in reverse chronological order.  \n\n![Timeline](static/img/Timeline.GIF)\n\n## \u003ca name=\"#Search\"\u003e\u003c/a\u003eSearch Auditions\nTo filter through the cards, I developed a search feature by adding a JavaScript event listener that evaluates keystrokes to hide the cards that do not contain text matching the query string.\n\n![Search](static/img/Search.GIF)\n\n## \u003ca name=\"#Input\"\u003e\u003c/a\u003eAudition Input\nTo collect the user's data, I built a responsive form which provides intuitive prompts--he first of which is whether the audition is an initial audition or a callback. When the user clicks the callback button, an on-click event triggers a drop down to appear with previously logged projects, which the user can then select. I implemented jQuery to auto-populate certain text fields with response data returned from my server via a get request made to my API. \n\n![Form](static/img/Form.GIF)\n\n## \u003ca name=\"#Location\"\u003e\u003c/a\u003eLocation and Media\nI implemented Google’s Map \u0026 Places API with their Place Autocomplete service. In addition, by integrating Cloudinary’s media management API, I am able to offer the user the option of uploading any number or type of media files pertaining to their audition.\n\n![Input](static/img/Form2.GIF)\n\n## \u003ca name=\"#Media\"\u003e\u003c/a\u003eView Media\n In order to correctly populate the media table in my database with multiple files, promises returned from both my API and Cloudinary’s needed to be handled in a synchronized manner using a series of async/await fetch requests. I originally wrote this code with a series of nested fetches, but refactoring with async/await allowed me to store the responses in variables, which proved to be very helpful for debugging.\n Update - I now handle the media upload more securely on the backend! See the upload-cloudinary route in my server. \n\n![Media](static/img/Media.GIF)\n\n## \u003ca name=\"#Audition\"\u003e\u003c/a\u003eAudition Statistics\nI used the ChartJS data visualization library to build statistical representations of the user's auditions. The bar chart represents the total number of auditions logged by the user over time, while the two doughnut charts break auditions down by industry and agency. I was able to display the data by month and by year while giving each year its own color by putting the data into a nested object and parsing through it.\n\n![Statistics](static/img/Stats.GIF)\n\n## \u003ca name=\"#Data\"\u003e\u003c/a\u003eData Model\n\n![SQLDBM](static/img/SQLDBM.png)\n\n## \u003ca name=\"#Future\"\u003e\u003c/a\u003eLooking Ahead\nMoving forward, I will be continuing to develop my application’s use of the Twilio API to allow users to better share an audition card via SMS.\n\n![Moving Forward](static/img/Future.jpg)\n\n## \u003ca name=\"#Meet\"\u003e\u003c/a\u003eMeet the Developer\n\nA tenacious multi-hyphenate, I am a driven and focused problem solver who has a knack for seeing the bigger picture in any situation. I currently work for Cloudinary as a Software Engineering Tutorial Producer. From 2013-2021, I was the Senior Operations Manager at a private investment office in NYC, where I was promoted twice within the company.\n\nI also have a successful career as a commercial, tv, film, theatre, and voiceover actress and model in New York City. I hold a BFA from the UC-Conservatory of Music, which accepts only the top 1% of applicants for my given major.\nI am a contributing member and co-founder of the mentorship program within Artists Who Code, an online community of artists in tech. In my free time, I am an adventurous world traveler who enjoys mountain biking, snowboarding, running, scuba diving, pickleball, and am happiest in hiking boots.\n\nConnect with [Jen Brissman](https://www.linkedin.com/in/jenbrissman/) on LinkedIn!\n\n## \u003ca name=\"#Troubleshooting\"\u003e\u003c/a\u003eTroubleshooting\nIf you are trying to reseed the database (never do this in production), it isn't enough to drop the database.\nYou also need to drop the schema entirely.\n- To drop the schema, execute this SQL command: `drop schema public cascade;`\n- To recreate the schema, execute this SQL command: `create schema public;`\n\n## \u003ca name=\"#Acknowledgments\"\u003e\u003c/a\u003eAcknowledgments\n\n#### Mentors\n- Anna Peery\n- Kerrie Yee\n- Kevin Krauss\n- Jordan Grubb\n- Yaakov Bressler\n\n#### Advisors\n- Thu Nguyen\n- Kat Huber-Juma\n- Lucia Racine\n\n## \u003ca name=\"#Install\"\u003e\u003c/a\u003eInstall\n\n### Running Followspot\n\n1. Clone this repository:\n```shell\ngit clone https://github.com/jenbrissman/FollowSpot.git\n```\n\n***Optional***: Create and activate a virtual environment:\n```shell\npip3 install virtualenv\nvirtualenv env\nsource env/bin/activate\n```\n\n2. Install dependencies: \n```shell\npip3 install -r requirements.txt\n```\n\n3. Create environmental variables to hold your API keys in a `secrets.sh` file. You'll need to create your own Twilio and Cloudinary API keys:\n```\nexport cloud_name=\"create your own cloudindary name/account\"\nexport cloud_api_key=\"once you do this they will provide you a key which you will put here\"\nexport cloud_api_secret=\"use your own secret of course, shhh\"\nexport twilio_account_sid=\"create your own twilio account and enter your sid here\"\nexport twilio_auth_token=\"enter your twilio auth token here\"\nexport twilio_number=\"+15555555555 enter your assigned twilio # with the +1 format before 10 digit #\"\n```\n\n4. Create your database \u0026 seed sample data:\n```shell\ncreatedb followspot\npython3 seed.py\n```\n\n5. Run the app on localhost:\n```shell\nsource secrets.sh\npython3 server.py\n```\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjenbrissman%2Ffollowspot","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjenbrissman%2Ffollowspot","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjenbrissman%2Ffollowspot/lists"}