Skip to content

Commit 8552926

Browse files
committed
Update README for clarity and correctness
- Add a dedicated compatibility section detailing supported Python and Django versions. - Simplify the `INSTALLED_APPS` setup instruction. - Clarify the behavior of the `stream` parameter and its future default value. - Provide a warning about HTML customization limitations with the Next.js App Router. - Enhance overall readability, accuracy of setup instructions, and usage examples. - Correct minor grammatical errors and typos.
1 parent 6fc9c79 commit 8552926

File tree

1 file changed

+63
-107
lines changed

1 file changed

+63
-107
lines changed

README.md

Lines changed: 63 additions & 107 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,11 @@
88
Integrate Next.js into your Django project,
99
allowing Django and Next.js pages to work together seamlessly.
1010

11+
## Compatibility
12+
13+
- Python: **3.9**, **3.10**, **3.11**, **3.12**, **3.13**
14+
- Django: **4.2**, **5.0**, **5.1**, **5.2**
15+
1116
## Is this package right for you?
1217

1318
django-nextjs is designed for projects
@@ -19,34 +24,30 @@ that need both Django pages (usually rendered by Django templates) and Next.js p
1924
If this sounds like you, **this package is the perfect fit**. ✅
2025

2126
However, if you’re starting a new project and intend to use Django purely as an API backend with Next.js as a standalone frontend, you **don’t need** this package.
22-
Simply run both servers and configure your public web server to point to Next.js for a straightforward setup.
27+
Simply run both servers and configure your public web server to route requests to Next.js; this provides a more straightforward setup.
2328

2429
## How does it work?
2530

26-
When a user opens a page, django receives the initial request, queries the Next.js server for the HTML response, and returns it to the user.
31+
When a user opens a page, Django receives the initial request, queries the Next.js server for the HTML response, and returns it to the user.
2732
After opening a Next.js page, the user can navigate to other Next.js pages without any additional requests to Django (the Next.js server handles the routing).
2833

29-
This is how it looks like in production:
34+
This is what it looks like in production:
3035

3136
![How it works in production](.github/assets/how-it-works-production.webp)
3237

33-
In development, to simplify the setup and remove the need to a reverse proxy like Nginx, Django also acts as the reverse proxy for Next.js client-side requests.
34-
35-
## Getting Started
38+
In development, to simplify the setup and remove the need for a reverse proxy like Nginx, Django also acts as the reverse proxy for Next.js client-side requests.
3639

37-
- Install the latest version from PyPI.
40+
## Getting started
3841

39-
```shell
40-
pip install django-nextjs
41-
```
42+
Install the latest version from PyPI:
4243

43-
- Add `django_nextjs.apps.DjangoNextJSConfig` to `INSTALLED_APPS`.
44-
45-
- Set up Next.js URLs depending on your environment.
44+
```shell
45+
pip install django-nextjs
46+
```
4647

47-
## Setup Next.js URLs (Development Environment)
48+
Add `django_nextjs` to `INSTALLED_APPS`.
4849

49-
Configure your `asgi.py` with `NextJsMiddleware` as shown below:
50+
Configure your project's `asgi.py` with `NextJsMiddleware` as shown below:
5051

5152
```python
5253
import os
@@ -91,7 +92,7 @@ urlpatterns = [
9192
> [!IMPORTANT]
9293
> Using ASGI is **required**
9394
> for [fast refresh](https://nextjs.org/docs/architecture/fast-refresh)
94-
> to work properly in Next.js 12+.
95+
> to work properly in Next.js 12 and later.
9596
> Without it, you'll need to manually refresh your browser
9697
> to see changes during development.
9798
>
@@ -100,17 +101,17 @@ urlpatterns = [
100101
> or [Uvicorn](https://www.uvicorn.org/).
101102
102103

103-
## Setup Next.js URLs (Production Environment)
104+
## Setup Next.js URLs in production
104105

105-
In production, use a reverse proxy like Nginx or Caddy:
106+
In production, use a reverse proxy like Nginx or Caddy.
106107

107-
| URL | Action |
108-
| ------------------- | ------------------------------------------ |
109-
| `/_next/static/...` | Serve `NEXTJS_PATH/.next/static` directory |
110-
| `/_next/...` | Proxy to `http://localhost:3000` |
111-
| `/next/...` | Serve `NEXTJS_PATH/public/next` directory |
108+
| URL | Action |
109+
|---------------------|-------------------------------------------------------------|
110+
| `/_next/static/...` | Serve `NEXTJS_PATH/.next/static` directory |
111+
| `/_next/...` | Proxy to the Next.js server (e.g., `http://127.0.0.1:3000`) |
112+
| `/next/...` | Serve `NEXTJS_PATH/public/next` directory |
112113

113-
Example config for Nginx:
114+
Example Nginx configuration:
114115

115116
```conf
116117
location /_next/static/ {
@@ -134,76 +135,51 @@ location /next/ {
134135

135136
## Usage
136137

137-
Start Next.js server:
138-
139-
```shell
140-
# Development:
141-
$ npm run dev
142-
143-
# Production:
144-
$ npm run build
145-
$ npm run start
146-
```
138+
Start the Next.js server using `npm run dev` or `npm run start` (depending on the environment).
147139

148-
Start by developing your pages in Next.js, Then define a Django URL for each Next.js page. Here's an example of how you can do this:
140+
For each Next.js page, define a Django URL that will render the page using the `nextjs_page` view.
149141

150142
```python
151143
from django_nextjs.views import nextjs_page
152144

153145
urlpatterns = [
154-
path("/nextjs/page", nextjs_page(), name="nextjs_page"),
155-
]
156-
```
157-
158-
Even though it's not recommended, sometimes you might need to add some custom steps before showing a Next.js page in Django. However, **we advise moving this logic to Next.js to ensure it's applied even during client-side navigation**. If you find yourself in this situation, you can create an asynchronous view for each page as demonstrated below:
159-
160-
```python
161-
from django_nextjs.render import render_nextjs_page
162-
163-
async def jobs(request):
164-
# Your custom logic
165-
return await render_nextjs_page(request)
166-
```
167-
168-
#### Using `nextjs_page` with `stream=True` (Recommended)
169-
170-
If you're using the [Next.js App Router](https://nextjs.org/docs/app) (introduced in Next.js 13+), you can enable streaming by setting the `stream=True` parameter in the `nextjs_page` function. This allows the HTML response to be streamed directly from the Next.js server to the client. This approach is particularly useful for server-side rendering with streaming support to show an [instant loading state](https://nextjs.org/docs/app/building-your-application/routing/loading-ui-and-streaming#instant-loading-states) from the Next.js server while the content of a route segment loads.
171-
172-
Here's an example:
146+
path("/my/page", nextjs_page(), name="my_page"),
173147

174-
```python
175-
from django_nextjs.views import nextjs_page
176-
177-
urlpatterns = [
178-
path("/nextjs/page", nextjs_page(stream=True), name="nextjs_page"),
148+
# To enable streaming, set stream=True (recommended)
149+
path("/other/page", nextjs_page(stream=True), name="other_page"),
179150
]
180151
```
181152

182-
**Considerations:**
153+
### The `stream` parameter
154+
155+
If you're using the [Next.js App Router](https://nextjs.org/docs/app) (introduced in Next.js 13), you can enable streaming by setting the `stream` parameter to `True` in the `nextjs_page` function. This allows the HTML response to be streamed directly from the Next.js server to the client. This approach is particularly useful for server-side rendering with streaming support to display an [instant loading state](https://nextjs.org/docs/app/building-your-application/routing/loading-ui-and-streaming#instant-loading-states) from the Next.js server while the content of a route segment loads.
183156

184-
- When using `stream_nextjs_page`, you cannot use a custom HTML template in Django, as the HTML is streamed directly from the Next.js server.
185-
- The `stream` parameter will default to `True` in future releases. Currently, it is set to `False` for backward compatibility. To avoid breaking changes, we recommend explicitly setting `stream=False` if you are customizing HTML and do not want to use streaming.
157+
Currently, the default value for this parameter
158+
is set to `False` for backward compatibility.
159+
It will default to `True` in the next major release.
186160

187-
## Customizing the HTML Response
161+
## Customizing the HTML response
188162

189163
You can modify the HTML code that Next.js returns in your Django code.
190164

191-
Avoiding duplicate code for the navbar and footer is a common use case
192-
for this if you are using both Next.js and Django templates.
165+
> [!WARNING]
166+
> This feature is not compatible with the Next.js App Router, and to use it,
167+
> you need to set the `stream` parameter to `False` in the `nextjs_page` function.
168+
> Because of these limitations, we do not recommend using this feature.
169+
> For more details, please refer to [this GitHub issue](https://github.com/QueraTeam/django-nextjs/issues/22).
170+
171+
This is a common use case for avoiding duplicate code for the navbar and footer if you are using both Next.js and Django templates.
193172
Without it, you would have to write and maintain two separate versions
194173
of your navbar and footer (a Django template version and a Next.js version).
195174
However, you can simply create a Django template for your navbar and insert its code
196-
at the beginning of `<body>` tag returned from Next.js.
175+
at the beginning of the `<body>` tag in the HTML returned by Next.js.
197176

198-
To enable this feature, you need to customize the document and root layout
199-
in Next.js and make the following adjustments:
177+
To enable this feature, you need to customize the Next.js `pages/_document` file and make the following adjustments:
200178

201-
- Add `id="__django_nextjs_body"` as the first attribute of `<body>` element.
179+
- Add `id="__django_nextjs_body"` as the first attribute of the `<body>` element.
202180
- Add `<div id="__django_nextjs_body_begin" />` as the first element inside `<body>`.
203181
- Add `<div id="__django_nextjs_body_end" />` as the last element inside `<body>`.
204182

205-
NOTE: Currently HTML customization is not working with [app router](https://nextjs.org/docs/app) (Next.js 13+).
206-
207183
Read
208184
[this doc](https://nextjs.org/docs/pages/building-your-application/routing/custom-document)
209185
and customize your Next.js document:
@@ -220,21 +196,6 @@ and customize your Next.js document:
220196
...
221197
```
222198

223-
<!-- If you are using Next.js 13+, you also need to
224-
[customize the root layout](https://nextjs.org/docs/app/api-reference/file-conventions/layout)
225-
in `app` directory:
226-
227-
```jsx
228-
// app/layout.jsx (or .tsx)
229-
...
230-
<body id="__django_nextjs_body" className={inter.className}>
231-
<div id="__django_nextjs_body_begin" />
232-
{children}
233-
<div id="__django_nextjs_body_end" />
234-
</body>
235-
...
236-
``` -->
237-
238199
Write a Django template that extends `django_nextjs/document_base.html`:
239200

240201
```django
@@ -257,31 +218,25 @@ Write a Django template that extends `django_nextjs/document_base.html`:
257218
{% endblock %}
258219
```
259220

260-
Pass the template name to `nextjs_page` or `render_nextjs_page`:
221+
Pass the template name to `nextjs_page`:
261222

262223
```python
263-
from django_nextjs.render import render_nextjs_page
264224
from django_nextjs.views import nextjs_page
265225

266-
async def jobs(request):
267-
return await render_nextjs_page(request, template_name="path/to/template.html")
268-
269226
urlpatterns = [
270-
path("/nextjs/page", nextjs_page(template_name="path/to/template.html"), name="nextjs_page"),
271-
path("/jobs", jobs, name="jobs_page")
227+
path("/my/page", nextjs_page(template_name="path/to/template.html"), name="my_page"),
272228
]
273-
274229
```
275230

276231
## Notes
277232

278-
- If you want to add a file to `public` directory of Next.js,
279-
that file should be in `public/next` subdirectory to work correctly.
233+
- If you want to add a file to the Next.js `public` directory,
234+
that file should be in the `public/next` subdirectory for it to work correctly.
280235
- If you're using ASGI, make sure all your middlewares are
281236
[async-capable](https://docs.djangoproject.com/en/dev/topics/http/middleware/#asynchronous-support).
282-
- To avoid "Too many redirects" error, you may need to add `APPEND_SLASH = False` in your Django project's `settings.py`. Also, do not add `/` at the end of nextjs paths in `urls.py`.
237+
- To avoid "Too many redirects" errors, you may need to add `APPEND_SLASH = False` in your Django project's `settings.py`. Also, do not add `/` at the end of Next.js paths in `urls.py`.
283238
- This package does not provide a solution for passing data from Django to Next.js. The Django Rest Framework, GraphQL, or similar solutions should still be used.
284-
- The Next.js server will not be run by this package. You will need to run it yourself.
239+
- This package does not start the Next.js server. You need to run it yourself.
285240

286241
## Settings
287242

@@ -297,25 +252,26 @@ NEXTJS_SETTINGS = {
297252

298253
### `nextjs_server_url`
299254

300-
The URL of Next.js server (started by `npm run dev` or `npm run start`)
255+
The URL of the Next.js server (started by `npm run dev` or `npm run start`)
301256

302257
### `ensure_csrf_token`
303258

304259
If the user does not have a CSRF token, ensure that one is generated and included in the initial request to the Next.js server by calling Django's `django.middleware.csrf.get_token`. If `django.middleware.csrf.CsrfViewMiddleware` is installed, the initial response will include a `Set-Cookie` header to persist the CSRF token value on the client. This behavior is enabled by default.
305260

306-
**When you need `ensure_csrf_token`?**
307-
308-
You may need to issue GraphQL POST requests to fetch data in Next.js `getServerSideProps`. If this is the user's first request, there will be no CSRF cookie, causing the request to fail since GraphQL uses POST even for data fetching.
309-
In this case this option solves the issue,
310-
and as long as `getServerSideProps` functions are side-effect free (i.e., they don't use HTTP unsafe methods or GraphQL mutations), it should be fine from a security perspective. Read more [here](https://docs.djangoproject.com/en/3.2/ref/csrf/#is-posting-an-arbitrary-csrf-token-pair-cookie-and-post-data-a-vulnerability).
261+
> [!TIP]
262+
> **The use case for this option**
263+
>
264+
> You may need to issue GraphQL POST requests to fetch data in Next.js `getServerSideProps`. If this is the user's first request, there will be no CSRF cookie, causing the request to fail since GraphQL uses POST even for data fetching.
265+
> In this case, this option solves the issue,
266+
> and as long as `getServerSideProps` functions are side-effect free (i.e., they don't use HTTP unsafe methods or GraphQL mutations), it should be fine from a security perspective. Read more [here](https://docs.djangoproject.com/en/3.2/ref/csrf/#is-posting-an-arbitrary-csrf-token-pair-cookie-and-post-data-a-vulnerability).
311267
312268
### `dev_proxy_paths`
313269

314270
A list of paths that should be proxied to the Next.js server in development mode.
315271

316-
This is useful if you want to use a custom path instead of `/next` inside the `public` directory of Next.js.
272+
This option is useful if you want to use a custom path instead of `/next` inside the Next.js `public` directory.
317273
For example, if you want to use `/static-next` instead of `/next`, you can set `proxy_paths` to `["/_next", "/__next", "/static-next"]`
318-
and place your static files in `public/static-next` directory of Next.js.
274+
and place your static files in the `public/static-next` directory.
319275
You should also update the production reverse proxy configuration accordingly.
320276

321277
## Contributing
@@ -325,7 +281,7 @@ To start development:
325281
- Install development dependencies in your virtualenv with `pip install -e '.[dev]'`
326282
- Install pre-commit hooks using `pre-commit install`.
327283

328-
Love django-next.js? 🌟 Star us on GitHub to help the project grow!
284+
Love django-nextjs? 🌟 Star us on GitHub to help the project grow!
329285

330286
## License
331287

0 commit comments

Comments
 (0)