thinknimble / tn-spa-bootstrapper Goto Github PK
View Code? Open in Web Editor NEWA production-ready Django SPA app on Heroku in 20-min or less!
Home Page: https://tn-spa-bootstrapper-staging.herokuapp.com/
License: MIT License
A production-ready Django SPA app on Heroku in 20-min or less!
Home Page: https://tn-spa-bootstrapper-staging.herokuapp.com/
License: MIT License
I tried to start a project but did not want a backend I figured I could just delete it after it was generated however when I was going through the steps I did not select a provider for static files so it failed
ERROR: Stopping generation because pre_gen_project hook script didn't exit successfully
Maybe either add selection for no backend or set one by default if non are selected.
apollo-link packages have been deprecated by the apollo team : https://github.com/apollographql/apollo-link
Apparently they are already including the same functionalities in their v3 (which is already part of our react client)
https://www.apollographql.com/docs/react/migrating/apollo-client-3-migration/#apollo-link-
Seems like the only change required is to replace the imports to point to:
import {createHttpLink} from '@apollo/client/link/http'
import {setContext} from '@apollo/client/link/context'
Cypress is designed to stay in a failure state until it's able to run against the latest version of the code deployed on Heroku.
There error given in that failure state isn't clear:
We should show a custom error instead and say something like:
If this error just happened, wait a few minutes as the Heroku deployment likely hasn't finished yet.
This test will automatically re-run when the app is ready to be tested.
If this error has been here for more than a few minute, check Heroku.
There was likely an error while building/deploying the application.
Need to update handleRegistrationSuccess()
in Vue client signup view.
Need to add auth-state update similar to what is found in handleLoginSuccess()
in the login view.
Cookies are needed for csrf I've seen us use this one
utils/cookie.ts
export default function getCookie(cname: string): string {
const name = cname + '='
const decodedCookie = decodeURIComponent(document.cookie)
const ca = decodedCookie.split(';')
for (let i = 0; i < ca.length; i++) {
let c = ca[i]
while (c.charAt(0) === ' ') {
c = c.substring(1)
}
if (c.indexOf(name) === 0) {
return c.substring(name.length, c.length)
}
}
return ''
}
services/axios-instance.ts
to add the cookie to the headerimport getCookie from '../utils/cookie'
const csrfToken = getCookie('csrftoken')
const axiosInstance = axios.create({
//baseUrl will be determined by the server proxy in vite.config.js
headers: {
'Content-Type': 'application/json',
'X-CSRFToken': csrfToken,
},
In: clients/vue3/services/api.js
apiErrorHandler() fails to rethrow error if enable400Alert
is set to true
.
This is due to an early return that needs to be reworked.
The Bootstrapper should support running applications under Docker. Ideally this will eliminate the need to support multiple operating systems when running the bootstrapper initialization process.
Change Pillow to version 9.0 to support python 3.10.5 (Heroku's 22 stack supports 3.9.13 & 3.10.5) the version 8.3.1 (in the BS) only supports up to 3.9 - there is also version 9.3 which also supports python 3.11
Login and account creation now exist, so we should add Cypress test support with one or two thoughtful test examples.
For simplicity, Cypress should point at the Heroku Review App for a PR and should point to Staging when it is run against the main branch.
When generating a Vue/Django app with the bootstrapper, missing URL routes aren't handled correctly.
We should handle 404s properly with an acceptable default page for newly generated projects.
To reproduce:
cookiecutter
command as usualcd
into your new projectmake build
or docker compose build
The build will fail because Pipfile.lock does not exist.
To get Pipfile.lock to exist, you would have to run pipenv install locally, which means you have to make sure Python and pipenv are set up properly on your local. IMO this defeats the purpose of using docker to contain these dependencies.
Options to discuss:
Add Pytest support and write one or two thought tests as examples.
Should run automatically for all PRs.
These tests are for the generated project, but should be run on bootstrapper PRs as well (if we can) to validate that new bootstrapper changes don't break functionality in the generated apps.
There is existing logic for plaintext emails server/my_project/utils/emails.py, but there are a couple of issues:
EMAIL_BACKEND
is set to console we end up logging the entire HTML email content.project-specific naming, instead of server
. Because if we have multiple projects locally, there would be collisions in Docker
We have some pytest-cookies tests written for flake8 and black, but they are failing because the generated project is not compliant. Once we merge #12, we should quickly follow up with a PR fixing all the linting issues and then re-enable those tests.
Currently the Cypress tests run when the other tests run. The problem is that Heroku finishes deploying the new changes after the tests run, so the Cypress results are actually for the previous code push.
Better solutions:
repository_dispatch
Apparently it's not working anymore.
Rather than creating a separate array for specifying which are the public routes. We can leave public routes to be at the top of the router declaration, and add a Private routes auth guard instead. Similar to what we did in the The Drop:
Declaring private routes:
Declaring Root Routes (thus, public)
https://github.com/thinknimble/share-the-drop-web/blob/0d8be46067bfa169923f4f7506b1f6a1dc428eae/src/routes/index.tsx#L91-L106
I'm wondering whether having chakra-ui as default in React client is a good fit.
Feels like Chakra ui has a lot of functionalities (and overhead to learn specifics of the library itself) that many new projects might not need from the very beginning.
I see the Vue client does not have any component library as default but instead it has tailwind, which I believe is a perfect styling starter for any project.
If a given project strives for a component library then that specific project could add chakra-ui for their use.
PS: I've also had some trouble with testing components that used Chakra ( #133 has some links in the comments) so I might be a little bit triggered and biased regarding chakra, I'd love your thoughts here!
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<!-- NOTE: You can use the template tag %PUBLIC_URL% here. -->
<!-- Standard title and description -->
<title>SAMPLE</title>
<meta name="description" content="SAMPLE project" />
<!-- Favorite icons for web browsers and mobile devices -->
<!-- Generate these using a SQUARE image at favicon-generator.org -->
<link rel="icon" href="favicon.ico" type="image/x-icon" />
<link rel="apple-touch-icon" sizes="57x57" href="/static/static/favicons/apple-icon-57x57.png" />
<link rel="apple-touch-icon" sizes="60x60" href="/static/static/favicons/apple-icon-60x60.png" />
<link rel="apple-touch-icon" sizes="72x72" href="/static/static/favicons/apple-icon-72x72.png" />
<link rel="apple-touch-icon" sizes="76x76" href="/static/static/favicons/apple-icon-76x76.png" />
<link rel="apple-touch-icon" sizes="114x114" href="/static/static/favicons/apple-icon-114x114.png" />
<link rel="apple-touch-icon" sizes="120x120" href="/static/static/favicons/apple-icon-120x120.png" />
<link rel="apple-touch-icon" sizes="144x144" href="/static/static/favicons/apple-icon-144x144.png" />
<link rel="apple-touch-icon" sizes="152x152" href="/static/static/favicons/apple-icon-152x152.png" />
<link rel="apple-touch-icon" sizes="180x180" href="/static/static/favicons/apple-icon-180x180.png" />
<link rel="icon" type="image/png" sizes="192x192" href="/static/static/favicons/android-icon-192x192.png" />
<link rel="icon" type="image/png" sizes="32x32" href="/static/static/favicons/favicon-32x32.png" />
<link rel="icon" type="image/png" sizes="96x96" href="/static/static/favicons/favicon-96x96.png" />
<link rel="icon" type="image/png" sizes="16x16" href="/static/static/favicons/favicon-16x16.png" />
<link rel="manifest" href="/manifest.json" />
<meta name="msapplication-TileColor" content="#ffffff" />
<meta name="msapplication-TileImage" content="/ms-icon-144x144.png" />
<!-- Theme color: Usually the app's brand color -->
<meta name="theme-color" content="#F2615A" />
<!-- Facebook Unfurling Meta Tags -->
<meta property="og:type" content="website" />
<meta property="og:url" content="%PUBLIC_URL%" />
<meta property="og:title" content="{{ cookiecutter.project_name }}" />
<meta property="og:description" content="Add a description for {{ cookiecutter.project_name }} in index.html!" />
<meta property="og:image" content="%PUBLIC_URL%/static/meta-preview.png" />
<!-- Twitter Unfurling Meta Tags -->
<meta name="twitter:card" content="summary_large_image">
<!-- TODO: Add the app domain here once live. -->
<!-- <meta name="twitter:domain" value="" /> -->
<meta name="twitter:title" value="{{ cookiecutter.project_name }}" />
<meta name="twitter:description" value="Add a description for {{ cookiecutter.project_name }} in index.html!" />
<meta name="twitter:image" content="%PUBLIC_URL%/static/meta-preview.png" />
<meta name="twitter:url" value="%PUBLIC_URL%" />
<!-- Optional: Add a Twitter handle -->
<!-- <meta name="twitter:site" content="@MyTweets"> -->
<script type="module" crossorigin src="/static/assets/index.ab0d53c0.js"></script>
<link rel="stylesheet" href="/static/assets/index.dbdc8057.css">
</head>
<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root"></div>
<!--
This HTML file is a template.
If you open it directly in the browser, you will see an empty page.
You can add webfonts, meta tags, or analytics to this file.
The build step will place the bundled scripts into the <body> tag.
To begin the development, run `npm start` or `yarn start`.
To create a production bundle, use `npm run build` or `yarn build`.
-->
</body>
</html>
Also quesiton is %PUBLIC_URL% supposed to render to something ?
Small typo leaves graphql in settings.py on the same line as another var causing a bug.
In all projects the backend proxy and api are served with the env variable VUE_APP_DEV_SERVER_BACKEND as this is the common verbiage we have been using lets replace this also in the axios config file
VUE_APP_DEV_SERVER_BACKEND=""
let base_url = process.env.VUE_APP_BASE_API_URL ? process.env.VUE_APP_BASE_API_URL :
${window.location.protocol}//${window.location.hostname}
See: https://github.com/joke2k/django-environ
This should simplify some of the common things we do in settings.py and help prevent dumb errors having to do with casting environment variable types from string to whatever else.
Currently the signals are imported inside the models.py according to django this is not advised.
https://docs.djangoproject.com/en/4.1/topics/signals/
One option is to import all signals in apps.py as such
class SomeAppConfig(AppConfig):
default_auto_field = "django.db.models.BigAutoField"
name = "some_project.some_app"
def ready(self) -> None:
# this import is required to register signals after the app is initialized
# https://docs.djangoproject.com/en/4.1/topics/signals/
import some_project.some_app.signals # noqa
return super().ready()
Alternatively a better approach is that you can import and connect to each signal @juliantn has an example
There was some left over test code in Home.vue that automatically tries to login a user. It was used to show the use of a custom helper called unwrap for the options api but is no longer needed
The title says it all. Let's use this thread to brainstorm better names for this repo.
Current steps in the README for installing cookiecutter have you do it into the global namespace. (not great)
We should probably just re-point our instructions to the office cookiecutter ones:
https://cookiecutter.readthedocs.io/en/stable/installation.html#install-cookiecutter
Add formation to app.json so that it does not use whatever is already on prod/staging,
"formation": {
"web": {
"quantity": 1,
"size": "free"
}
},
You will incur billing charges for dynos used based on the formation requested.
Currently bootstrapping a React/Django stack doesn't work reliably.
I noticed that send_html_email
is in the utils/misc.py file. I think that may lower awareness of this function too much, when we really should try to raise awareness of it. IMO, it's really, really useful and should be our default way of sending emails - everyone expects HTML emails these days. I'd recommend at least moving it to utils/emails.py or maybe even into the core Django app so it's more readily visible.
Open to suggestions. Maybe Django has a better built-in email sender nowadays?
It appears we have removed the instructions for favicons from the readme (there is a basic comment in the django route but it does not explain the process).
This is important because the urls for the favicons are hardcoded in a bootstrapped application, while we could use any favicon generator, the one that the routes are based off creates a bunch of different versions. If a user does not appropriately set up favicons and debug=False is set then the app will crash.
Unless we're using packages tied to react <18 (we can also upgrade them along with react!) we could definitely upgrade to the 18th version, it's been around for a while and seems stable enough.
CRA has been great for creating apps when there was no other big alternatives around, but has fallen behind both in performance and configurability compared to newer tools such as Vite.
The challenge in this step is probably set up a couple of things (such as jest, eslint) that CRA brings out of the box while Vite does not
Typescript has just released 4.9 whereas we're using 3.9 in the project, we're a full major behind.
Hopefully this upgrade is seamless since there isn't that much code
Error when not opting to use heroku
Traceback (most recent call last):
File "/var/folders/8k/gz24nc91754gwxlxlcvkdj80000gn/T/tmpy81uyn_.py", line 423, in
main()
File "/var/folders/8k/gz24nc91754gwxlxlcvkdj80000gn/T/tmpy81uyn_.py", line 262, in main
remove_heroku_files()
File "/var/folders/8k/gz24nc91754gwxlxlcvkdj80000gn/T/tmpy81uyn_.py", line 103, in remove_heroku_files
os.remove(file_name)
Add Jest support and write one or two thoughtful tests as examples.
Should run automatically for all PRs.
These tests are for the generated project, but should be run on bootstrapper PRs as well to validate that new bootstrapper changes don't break functionality in the generated apps.
.npmrc
should be kept though!
Code in setup()
should be removed
There is a little clunkyness when deploying a bootstrapped app to production for the first time.
(TODO: comment below with specifics)
Several articles and tools are out there that can help with this.
One example:
https://github.com/lincolnloop/django-production
Looks like the server is not serving index.html generated from the client.
`
def index(request):
{% if cookiecutter.client_app.lower() == 'None' %}
return redirect(to="/docs/swagger/")
{% else %}
return render(request,'core/index-placeholder.html')
{% endif %}
`
@thinknimble/tn-validators
is still listed as a dependency for the project that the bootstrapper generates.
Pretty sure it's not used and can just be removed.
Per comments on #61
"I would suggest separating token management from the user model. I think it could potentially be dangerous to include an auth token in user payloads separate from authentication workflows. It just increases the likelihood that an auth token might show up in an API endpoint where it doesn't belong.
I'd also then create store actions for obtaining a token, verifying a token, and for logout. The /verify endpoint and action are especially necessary if using tokens that can expire - like JWTs - which need to be periodically renewed.
...
You also need to consider the case where an auth-protected page is accessed from an external link or page refresh. There might be a user in the store, but you should validate their API token and redirect them before showing the page.
...
I used a convenient composable that effectively added a layer of extra code but made it easier to use the store and not have to call commit/dispatch on each store mutation/action. It also meant I didn't have to keep importing the whole store, instead I would just import the constants I would need.
One caveat is it wont work in a regular js file so in the axios you still import the store but everywhere else you can just import the composable and declare the constants you want to use."
Eventually it would be nice to run tests as well but a low hanging fruit is just linting so we can catch issues related to if/else cookiecutter blocks.
The idea here being that we generate X number of projects in Github Actions. Just generating the code in separate folders. Then run the linters against those folders.
This will help us catch issues where linting is fine, unless you answer yes/no to a certain step and then injected code has a linting problem.
Newly bootstrapped projects should not have CI/CD errors on day 1.
When the project is not using gql, it makes more sense to include axios instead of apollo.
Since we're not differentiating with using gql/rest on React client creation, it would be nice to have the placeholders for both approaches.
Current implementation is broken (creating and setting passwords does so without the hashing algorithm), login authentication fails
TODO:
Currently bootstrapping a Vue/Django stack doesn't work reliably.
Our React and Vue apps currently use Node 14 and a corresponding NPM version. We should bump this up to something more recent like Node 18 and fix any corresponding package issues (node-sass usually has trouble with node version upgrades).
Discussion thread about auto-generating documentation.
What are the possible cases?
What are the possible tools?
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.