Giter VIP home page Giter VIP logo

ouroboros's Introduction

codecov

๐Ÿ Hiss

An open-source, hackathon registration system. ๐Ÿซ

โ“ Questions

If you have questions, we might've answered them already on the wiki! Check it out.

๐Ÿ’ป Running Locally

Local Development

For local development, we highly encourage using Docker Compose.

After Docker Compose is installed, there are just a few steps left for first-time setup:

docker-compose up -d
docker-compose exec db su postgres # Currently on host, moving into container
psql # Currently in container, moving into PostgreSQL prompt 

Now that you're in the PostgreSQL prompt, just run

CREATE DATABASE hiss;

This will create the database for you, and you're done with setup!

exit # In the PostgreSQL prompt, moving to container
exit # In the container, moving to the host

Now that you're on the host machine, just run the following:

docker-compose run web python3 manage.py makemigrations # Only if you modified models.py or forms.py
docker-compose run web python3 manage.py migrate --run-syncdb
docker-compose exec web python3 manage.py loaddata application/fixtures/schools.json # Loads in schools for school dropdown in application
docker-compose run web python3 manage.py createsuperuser # Enter details for an admin user to access the admin panel.

You're all set! Just run docker-compose up and you're good to go!

Mimic Production

To mimic a real production environment, a docker-compose.prod.yml file has been included in the repository for you to use.

This file is set up on the assumption that you are using Mailgun as your team's email provider.

To use it, simply replace the values in docker-compose.prod.yml with the values you need, and run

docker-compose -f docker-compose.yml -f docker-compose.prod.yml up

Staging Environment

We also have a staging environment Github Action workflow. To run this, simply create another heroku app, set HEROKU_APP_NAME in .github/workflows/staging.yml to the name of the heroku app, and push to a non-protected branch.

In order for the staging environment to work, you must connect a Heroku Postgres instance to the app. Anytime you change models or forms and make a new migration, you must manually sync the database in the heroku console.

To do this, push to the staging environment, open the Heroku bash shell, and run the following command:

python3 manage.py migrate --run-syncdb

Contributing

Install Poetry. Once installed, navigate to the root of the project and run the following:

poetry install
poetry run autohooks activate

This enables pre-commit hooks to make sure your code is formatted prooperly, so you won't get blocked in a PR.

Brought to you by

TAMUhack

ouroboros's People

Contributors

abhishek-more avatar adilras avatar cameron3301 avatar cameronbrill avatar dependabot[bot] avatar eightants avatar gracefank avatar jadenbanze avatar jay-khatri avatar jonathan-innis avatar juanrtech avatar kevinkuriachan avatar mopositive2001 avatar nitroguy10 avatar onewebdev avatar saltyquetzals avatar samarthdave avatar shreyanakkala avatar skandrigi avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

ouroboros's Issues

Expose authentication to non-web clients

Is your feature request related to a problem? Please describe.
The QR code reader app will need to authenticate with Django, but isn't necessarily a browser-based solution.

Describe the solution you'd like
An exposed authentication route supporting basic authentication using Django Rest Framework.

Styling needs help

The styling on a few pages needs some help:

  • error.html (base template)

  • 400.html (inherits from error)

  • 403.html (inherits from error)

  • 404.html (inherits from error)

  • 500.html (inherits from error)

  • check_email.html (tells user to check their email)

  • rsvp.html (with the new showable/hideable form, the styling needs to be updated)

Our email templates also need styling, if we want to make sure that they're branded.

  • emails/*.html

However, this makes it seem like CSS in emails is going to be a pain. I think that this library will help a bit, but the emails might need to be a bit plainer this year than they were last.

Wave inactive when created for current date

Describe the Bug
When a wave is created by an administrator, the wave does not register as being an active wave on the /status page.

To Reproduce

  1. Start a new wave (this should be the only wave) in the Django admin dashboard
  2. Create the wave with the start date of today
  3. Go to /status

Expected behavior
The user is invited to apply during the active wave.

Screenshots
Screenshot from 2019-06-19 22-19-18

AUTH_USER_MODEL throwing "No Such Table" Exception

Describe the Bug
After cloning the repository and setting up a virtual environment, I'm unable to make migrations.

I suspect that this bug is caused by the AUTH_MODEL_USER setting in the settings.py file of the ouroboros app.

To Reproduce
Steps to reproduce the behavior:

  1. Clone the GitHub repository
  2. Check out the dev_coffey branch
  3. Create a virtual environment and install the necessary dependencies
  4. python manage.py makemigrations

This should cause the error.

Expected behavior
Migrations should be made without Django complaining about tables being missing.

Screenshots

Traceback (most recent call last):
  File "Ouroboros/env/lib/python3.6/site-packages/django/db/backends/utils.py", line 85, in _execute
    return self.cursor.execute(sql, params)
  File "Ouroboros/env/lib/python3.6/site-packages/django/db/backends/sqlite3/base.py", line 296, in execute
    return Database.Cursor.execute(self, query, params)
sqlite3.OperationalError: no such table: hacker_hacker

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "manage.py", line 15, in <module>
    execute_from_command_line(sys.argv)
  File "Ouroboros/env/lib/python3.6/site-packages/django/core/management/__init__.py", line 381, in execute_from_command_line
    utility.execute()
  File "Ouroboros/env/lib/python3.6/site-packages/django/core/management/__init__.py", line 375, in execute
    self.fetch_command(subcommand).run_from_argv(self.argv)
  File "Ouroboros/env/lib/python3.6/site-packages/django/core/management/base.py", line 316, in run_from_argv
    self.execute(*args, **cmd_options)
  File "Ouroboros/env/lib/python3.6/site-packages/django/core/management/base.py", line 350, in execute
    self.check()
  File "Ouroboros/env/lib/python3.6/site-packages/django/core/management/base.py", line 379, in check
    include_deployment_checks=include_deployment_checks,
  File "Ouroboros/env/lib/python3.6/site-packages/django/core/management/base.py", line 366, in _run_checks
    return checks.run_checks(**kwargs)
  File "Ouroboros/env/lib/python3.6/site-packages/django/core/checks/registry.py", line 71, in run_checks
    new_errors = check(app_configs=app_configs)
  File "Ouroboros/env/lib/python3.6/site-packages/django/core/checks/urls.py", line 40, in check_url_namespaces_unique
    all_namespaces = _load_all_namespaces(resolver)
  File "Ouroboros/env/lib/python3.6/site-packages/django/core/checks/urls.py", line 57, in _load_all_namespaces
    url_patterns = getattr(resolver, 'url_patterns', [])
  File "Ouroboros/env/lib/python3.6/site-packages/django/utils/functional.py", line 37, in __get__
    res = instance.__dict__[self.name] = self.func(instance)
  File "Ouroboros/env/lib/python3.6/site-packages/django/urls/resolvers.py", line 533, in url_patterns
    patterns = getattr(self.urlconf_module, "urlpatterns", self.urlconf_module)
  File "Ouroboros/env/lib/python3.6/site-packages/django/utils/functional.py", line 37, in __get__
    res = instance.__dict__[self.name] = self.func(instance)
  File "Ouroboros/env/lib/python3.6/site-packages/django/urls/resolvers.py", line 526, in urlconf_module
    return import_module(self.urlconf_name)
  File "/usr/lib/python3.6/importlib/__init__.py", line 126, in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
  File "<frozen importlib._bootstrap>", line 994, in _gcd_import
  File "<frozen importlib._bootstrap>", line 971, in _find_and_load
  File "<frozen importlib._bootstrap>", line 955, in _find_and_load_unlocked
  File "<frozen importlib._bootstrap>", line 665, in _load_unlocked
  File "<frozen importlib._bootstrap_external>", line 678, in exec_module
  File "<frozen importlib._bootstrap>", line 219, in _call_with_frames_removed
  File "Ouroboros/ouroboros/urls.py", line 19, in <module>
    from core import views as core_views
  File "Ouroboros/core/views.py", line 8, in <module>
    from core import forms as core_forms
  File "Ouroboros/core/forms.py", line 51, in <module>
    class CreateApplicationForm(forms.ModelForm):
  File "Ouroboros/core/forms.py", line 56, in CreateApplicationForm
    choices=[(x.id, x.id) for x in hacker_models.Hacker.objects.all()],
  File "Ouroboros/env/lib/python3.6/site-packages/django/db/models/query.py", line 268, in __iter__
    self._fetch_all()
  File "Ouroboros/env/lib/python3.6/site-packages/django/db/models/query.py", line 1186, in _fetch_all
    self._result_cache = list(self._iterable_class(self))
  File "Ouroboros/env/lib/python3.6/site-packages/django/db/models/query.py", line 54, in __iter__
    results = compiler.execute_sql(chunked_fetch=self.chunked_fetch, chunk_size=self.chunk_size)
  File "Ouroboros/env/lib/python3.6/site-packages/django/db/models/sql/compiler.py", line 1065, in execute_sql
    cursor.execute(sql, params)
  File "Ouroboros/env/lib/python3.6/site-packages/django/db/backends/utils.py", line 100, in execute
    return super().execute(sql, params)
  File "Ouroboros/env/lib/python3.6/site-packages/django/db/backends/utils.py", line 68, in execute
    return self._execute_with_wrappers(sql, params, many=False, executor=self._execute)
  File "Ouroboros/env/lib/python3.6/site-packages/django/db/backends/utils.py", line 77, in _execute_with_wrappers
    return executor(sql, params, many, context)
  File "Ouroboros/env/lib/python3.6/site-packages/django/db/backends/utils.py", line 85, in _execute
    return self.cursor.execute(sql, params)
  File "Ouroboros/env/lib/python3.6/site-packages/django/db/utils.py", line 89, in __exit__
    raise dj_exc_value.with_traceback(traceback) from exc_value
  File "Ouroboros/env/lib/python3.6/site-packages/django/db/backends/utils.py", line 85, in _execute
    return self.cursor.execute(sql, params)
  File "Ouroboros/env/lib/python3.6/site-packages/django/db/backends/sqlite3/base.py", line 296, in execute
    return Database.Cursor.execute(self, query, params)
django.db.utils.OperationalError: no such table: hacker_hacker

Design and Implement Application model.

The Application model will represent the user's application to the hackathon. This should be an easily-modifiable part of the application, so things should be kept general and intuitive.

Application Form Styling Issues

  • Left/right margins on mobile are not aligned (white card is not centered, see img)
  • Change styling on radio buttons so they don't look like checkboxes (see Figma)
  • Change styling on checkboxes
  • Change select styling (see Figma)
  • Reduce select width to 50% instead of 100% on desktop (keep 100% on mobile)
  • Replace default select option from --------- to -- Select Option --
  • Q: What race(s) do you identify with -> align check boxes into 2 or 3 columns instead of by row
  • Reduce height of text-area by half for questions: tell us your best programming joke and after
  • Replace "Notes:" with Anything else you would like us to know?
  • Remove "Provide any additional notes and/or comments in the text box provided"
  • Style choose file button to upload resume (see Figma)
  • Reduce bottom padding/margin between question title and the form field by 20% of what it is currently
  • Add the following before the 18 or over question:
    - [ ] Add in first name field (pre-filled, but editable)
    - [ ] Add in last name field (pre-filled, but editable)
    - [ ] Add in email name field (pre-filled, but editable)
  • In point us to anything you'd like us to look at, change placeholder to be
    "ex. GitHub, Devpost, personal website, LinkedIn, etc."
  • Reorder questions:
    - [ ] Move Are you at least 18 or older to second to last last
    - [ ] Move provide us with any additional links below choose file for resume
    - [ ] Move provide "notes:"/anything else you want us to know to very last
  • Remove dietary restrictions question (move to rsvp)
  • Remove shirt size (move to rsvp) *also change shirt size from dropdown to radio box
  • Update resume question to reflect what's in the Application Questions google sheets
  • Add Do you require any special accommodations at the event? text field

"classification" field in HackerProfile

There's a field used in the HackerProfile, called classification that uses TAMU-centric student classifications ("U1", "U2", etc.). In order to keep this application school-agnostic, I think we should drop that field from the HackerProfile.

Automated deployment process (staging/prod)

Rather than worrying about deploying by hand over and over again, it makes more sense to build an automated deployment process using Google Cloud Build. It should:

  1. Run the Ouroboros tests
  2. Build the Ouroboros Docker container
  3. Push the container to GCR
  4. Update GKE

GCP has a pretty in-depth tutorial for this! It uses Google Cloud Source Repositories, but we can swap it out for GitHub.

NO_MORE_WAVES not handled by Status template

Describe the Bug
When accessing the /status route when there are no more active waves (whether all have passed or none were created), the NO_MORE_WAVES context provided by the StatusView is not handled, which results in an empty progress meter with no informative text.

To Reproduce
Steps to reproduce the behavior:

  1. Create an account
  2. Immediately go to /status

Expected behavior
An informative screen telling the hacker that registration is over.

Design and implement Hacker model

We'll need to design and implement the Hacker model that will serve as the core model in our application. It'll be the fundamental model that we attach Applications, Confirmations, and in the future, other model fields to.

multiple error messages

Describe the Bug
when you trigger an error, it doesn't disappear. multiple error messages pop up when page is updated with a new error

To Reproduce
Steps to reproduce the behavior:

  1. Go to signup page
  2. Force an error, press submit, see error message
  3. Force another error, press submit
  4. See two error messages

Expected behavior

  1. Force an error, press submit, see 1 error message
  2. Force a different error, press submit, see 2 error messages

Screenshots
here

Implement the Confirmation Model

-Create the Confirmation model in the hacker/models.py file

-Add fields (listed in the attached document) to the Confirmation model

-Add a __str__() function to the model

This function's return statement should return the id value
Add a comment to the end of this return statement that states: "This is a placeholder variable"

-ConfirmationModel document:

ConfirmationModel.txt

-ConfirmationModelInstructions document:

ConfirmationModelInstructions.txt

Allow admin to undo an rsvp no

Is your feature request related to a problem? Please describe.
I accidentally said no to rsvp

Describe the solution you'd like
Change the you can't rsvp after you relinquish your spot to "if you think this is a mistake, pls contact [email protected]"

Describe alternatives you've considered
Allow tamuhack admin to undo this

Additional context
gig'em

Under 18 attendance at HowdyHack

Describe the Bug
Users who say they are under 18 in the application process are allowed to submit applications, but we need to separate these users/do something else bc we're not really supposed to admit minors

To Reproduce
Steps to reproduce the behavior:

  1. Go to application
  2. fill out application
  3. enter no for under 18
  4. nothing happens

Expected behavior
idk what's meant to happen but we need to talk about this lol

Additional context
howdy

Add Volunteer user group

Is your feature request related to a problem? Please describe.
Apart from organizers, we'll need volunteers, who have permissions that are slightly elevated (so they can use Rattle).

Describe the solution you'd like
Creating a user group Volunteer that has permission to record events. Users should be added to the Volunteer group onsite via the admin interface.

Minor problems noticed

Some minor styling issues I noticed that might improve the look of the login /signup page, just some suggestions

  • Prevent users from entering numbers in the First Name and Last Name fields
  • The background color of the login and signup page differs, intentional?
  • Make 'HowdyHack 2019 Application' one line. Maybe specify if it's the login or signup page in the heading
  • Make the placeholder text in the input boxes a lighter grey and not italic, smaller placeholder text
  • LOGIN and REGISTER text on the buttons should be a smaller font size

Potential bugs but it might have just not been implemented yet

  • Forgot Password does nothing
  • After registering as expected like a normal hacker and confirming email, I reach a page with a progress bar and no other functionality except for logging out. Is that the end of the system?

Screenshot after confirming email, nothing else to do?
Capture5

Edit application questions & update RSVP form styling

APPLICATION

  • Make the following three fields not required:

     - Point us to anything you'd liked us to look at...
     - Do you require any special accommodations
     - Anything else you'd like us to know
    
  • Add "other" as an option for what's your major

  • Add "other" as an option for race

  • Add "other" as an option for gender

  • Add MLH Code of Conduct checkmark end of application

  • Make "Are you older than 18+" -> "Please confirm that you are 18+" and do a required checkbox instead of radio button

  • Add as a note to 18+ question: "Please note that freshmen under 18 must be accompanied by an adult or prove that they go to Texas A&M."

RSVP

  • Change RSVP yes/no buttons to radio buttons
  • When yes is selected, show dietary restrictions, shirt size, etc
  • When no is selected, show only submit button

Update `Hacker` model: Change inherited fields to required

The fields to be updated are listed below:
-'first_name'
-'last_name'
-'email'
These fields are inherited from the AbstractUser model and inherited as optional. The goal of this task is to change these fields to required.

This may involve overriding __init__() for the Hacker model which should be done carefully and thoughtfully.

Make sure to pull the most recent version of the Hacker model.

Note In the current Hacker model, there is a def create( โ€ฆ ) function. If you override __init__() successfully, this function (def create( โ€ฆ ) can be removed.

Add "Can't Make It" Action to Status

Users should be able to decline their invitation to the event, which helps give us a better idea as to whether we should accept more people or not.

Add MLH CoC

Is your feature request related to a problem? Please describe.
We need to add an agreement to abide by the MLH code of conduct to the application form. A simple checkbox is fine.

Describe the solution you'd like
Add the field to the Application model

Reduce input prompts space and make pages scrollable

This bug comes in two parts.

Describe the bug
On the Login page, enter an email and password that does not exist on the system. This will cause two error prompts that say the same thing to appear on the page "please enter a correct email and password..." This also pushes the bottom part of the login field down so the user is unable to click the Register link since you can't scroll.

On the Register page, entering a single letter password and a single letter first name will trigger three prompts that take up a lot of space and pushes most of the register field out of sight. You also can't scroll.

Expected behavior
Each prompt appears only once and prompts should take space such that the buttons aren't pushed out of sight.

Screenshots
These are the full pages, can't scroll down
Capture5
Capture4

Update `HackerProfile` model: Create grad_year_choices function

Create a function in the HackerProfile model that will automatically generate the options that will populate the GRAD_YEAR_CHOICES variable (which will subsequently be utilized in the grad_year field.

The GRAD_YEAR_CHOICES variable should always have 6 choices. These choices should be:
1. current_year
2. current_year + 1
3. current_year + 2
4. current_year + 3
5. current_year + 4
6. current_year + 5
where current_year is an integer value that represents the current year (at the time in which the function is being called).

404 Error; Needs an https:// in front of link to confirm your email

Describe the Bug
After opening your email to confirm your email, clicking on the link brings you to a 404 error page.

To Reproduce
Steps to reproduce the behavior:

  1. Go to your email after submission to create a new account.
  2. Click on the link.
  3. See error

Expected behavior
Should bring you to a page to confirm successful confirmation.

Screenshots
image

Application Form

Question order:

  • First name (text)
  • Last name (text)
  • Phone number (text; placeholder: )
  • School (text or drop-down?)
  • Major (text or drop-down?)
  • Grad date (drop-down)
  • Gender (drop-down)
  • Race (drop-down)
  • Transport method
  • How many hackathons before? (drop-down number, not counter)
  • Resume (upload)
  • Portfolio links (text; placeholder: ex. GitHub, Devpost, personal website, LinkedIn, etc.)
  • Programming joke (text)
  • Special accommodations? (text)
  • Additional comments (text)

Terms & Agreement:

  • Need to confirm 18+
  • Need to abide by mlh code of conduct or whatever code we're using or else they can't submit app

404 page just says "Resolver404"

Describe the Bug
Accessing the 404 page simply displays a page with the text Resolver404 displayed on it. Instead, it should display helpful text.

To Reproduce
Steps to reproduce the behavior:

  1. Go to /flibbertigibbet

Expected behavior
A 404 page should display with a helpful message stating why you got to that page.

Align misaligned center button on mobile for /status

Describe the Bug
When using Responsive Design Mode (browser emulation of mobile device viewports), the button in the center is aligned too far to the right, rather than to the left.

To Reproduce
Steps to reproduce the behavior:

  1. Using Firefox/Chrome
  2. Perform the processes required to get to the "Submitted" screen
  3. See error

Screenshots
Firefox
Chrome (iPhone X)

Additional context
iPhone X is used, but I anticipate any device with a small-enough viewport will perform similarly

Application name fields

Add the following before the 18 or over question:

  • Add in first name field (pre-filled, but editable)
  • Add in last name field (pre-filled, but editable)
  • Add in email name field (pre-filled, but editable)

Implement the HackerProfile Model

-Add fields (listed in the attached document) to the HackerProfile model:
>HackerProfile model has already been "created" so you'll just be adding to it (and testing it)

-Add a __str__() function to the model
>This function's return statement should return the id value
>Add a comment to the end of this return statement that states: "This is a placeholder variable"

-HackerProfileModel document:

HackerProfileModel.txt

-Document containing additional instructions:

HackerProfileModelInstructions.txt

Index route 404s

Describe the Bug
When accessing the index route of the site, the 404 page appears.

To Reproduce
Steps to reproduce the behavior:

  1. Access the index route with any configuration

Expected behavior
Should get redirected to /accounts/login

Additional context
Should be fixable in ouroboros/ouroboros/urls.py

Emails keep getting sent to spam

Describe the Bug
Ouroboros emails go straight to Gmail spam. I suspect this is because browsers aren't used to seeing emails from Sendgrid associated with TAMUhack.

To Reproduce

  1. Start Django in production mode
  2. Send an email to a Gmail account.

Expected behavior
An email to arrive in your primary inbox.

Additional context
This isn't a bug from misprogramming, but we could take some steps to increase "reputation" so the emails will send with no issue.

Add SSL to deployment config

Deployments right now are HTTP-based, which won't work for production (or staging).

Adding HTTPS will give users more confidence in the site. Ideally, this should either take the form of a Kubernetes Ingress, or a CloudFlare proxy.

GKE also has instructions for setting up Google-managed SSL certificates, though they're limited in scope.

Implement the Application Model

-Create the Application model in the hacker/models.py file

-Add fields (listed in the attached document) to the Application model

-Add a __str__() function to the model

This function's return statement should return the id value
Add a comment to the end of this return statement that states: "This is a placeholder variable"

-ApplicationModel document:

ApplicationModel.txt

Add Approval action when viewing individual Applications

When I click on an individual Application in the admin interface, I'd like to be able to approve that Application on that screen, so that way I don't have to deal with having to go back, selecting that specific Application again, and then approving it individually.

I think this link should be of some help.

Emails are sending HTML as raw content

Describe the Bug
Sending emails with an HTML attachment, rather than rendering as HTML, are simply displaying the HTML as raw text in the email.

The HTML itself is correct, but just rendered incorrectly.

Expected behavior
Rendered, visually-pleasing content

Screenshots
image

Create email verification page

When a user signs up, they're presented with a plaintext response that contains a helpful message, but doesn't look anything like the rest of the application. An email verification page would help make that transition less jarring.

RSVP Form Styling

  • Add the white card background (same style as all the other pages) to RSVP page)
  • Increase width of yes/no buttons to 25% of the width of its container
  • Change no to secondary button style (see figma)

Freezing and taking in bad input

Describe the Bug
The sign up page froze after a bad input.

To Reproduce
Steps to reproduce the behavior:

  1. Go to Sign Up page
  2. I used ***&&&&&@howdy.com and senpai123 for password
  3. Clicked submit
  4. See error

Expected behavior
Shouldn't work.

Screenshots
image

Additional context
On Chrome.

Add test for email verification workflow

Right now, there's no way to tell if the link sent out in verification emails is valid or not. It'd be nice to make tests for:

  • Happy path (that the verification email link, when clicked, activates the user)
  • Invalid verification tokens (make sure they expire)
  • Re-sending verification emails (assuming that their prior token has expired).

Update styling for templates

Current styling isn't really consistent with the new Howdy Hack landing page, we'll need to update each template's style so that they're consistent.

Web Templates

  • Login
  • Signup
  • Status
  • Application
  • RSVP

Email Templates

We should also be able to style the email templates so that they're consistent as well. I believe django-inlinecss is a good solution to this. Essentially, it just injects CSS stored in a different file into each corresponding element in the email (which is typically how it's done, anyway).

  • Email Verification
  • Password Reset
  • Application Submission
  • Acceptance/Rejection Email
  • Confirmation Submission
  • Check-in email

Clean email-templating solution

Right now, the event name in the password reset emails is hard-coded. This is because I can't (after 5 minutes of Googling) figure out a way to cleanly provide the customization context to the email templates.

Apparently, the context_processors setting of Django isn't applied when sending emails (which is kind of annoying). We could subclass the PasswordResetForm class used by Django, but I can't really figure out where to put it that makes it clean.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.