Opens an external site in a new window
Mental Health Awareness Month
“Community”
RODNEY LAB
  • Home
  • Plus +
  • Newsletter
  • Links
  • Profile
RODNEY LAB
  • Home
  • Plus +
  • Newsletter
  • Links

Astro JS non‑HTML Routes: File & Resource API # Astro JS non-HTML Routes: File & Resource API #

blurry low resolution placeholder image Astro JS non-HTML Routes
  1. Home Rodney Lab Home
  2. Blog Posts Rodney Lab Blog Posts
  3. Astro Astro Blog Posts
<PREVIOUS POST
NEXT POST >
LATEST POST >>

Astro JS non‑HTML Routes: File & Resource API #

Updated 2 years ago
6 minute read
Gunning Fog Index: 7.2
2 comments
Content by Rodney
blurry low resolution placeholder image Author Image: Rodney from Rodney Lab
SHARE:

🐝 Astro doesn’t Just do HTML! #

In this post on Astro JS non-HTML routes, we see how you can create file routes or resource routes in Astro. Astro specializes in delivering content sites and doing so quickly. However, that content does not have to be just HTML pages. In fact, we see a couple of examples of Astro non-HTML routes. In the first example, we generate and serve a PDF file from an API route. Then, in a second example, we create some JSON data (again from a resource route). You could extend this to create a JSON API. Although our examples focus on static Astro sites, we see the techniques can be adapted to work on Astro Server-side Rendered (SSR) sites too. With SSR, you can push the boat out, responding to Webhooks as well as generating next-gen images or even creating social sharing images for your site’s HTML pages.

🧱 Astro JS non‑HTML Routes #

If truth be told, there is not much to adding a non-HTML route to your Astro site. So instead of building a project from scratch, we will have a look at some example code. Hope that works for you! There is a repo with the complete code if you do want to see the entire picture. You can find a link further down the page for this.

blurry low resolution placeholder image Astro JS non-HTML Routes: screenshot of finished project shows a list of file routes linking to a P D F file and a J S O N file.
Astro JS non-HTML Routes: What we’re building

The idea, then, is to be able to link the resources from any HTML code on the site. Here, we put the links on the home page. Note there are other solutions, which might work better depending on your starting point or use case. Let’s say, for example, you have created a factsheet. You will serve the same factsheet to anyone who visits the site and clicks the link (no customization). Here, you could just place the PDF file for the factsheet in the public folder of your project. In fact, that folder is for anything which does not need processing by Vite. You could then link public/factsheet.pdf with an href /factsheet.pdf.

Static Astro JS non‑HTML routes #

Let’s take it up a notch. You still have your factsheet, however, you now want to pull in the latest available data each time you build your app as a static Astro site (the default). The factsheet might pull in data from external APIs, which change from time-to-time. We can generate the PDF at build time in our file route. Once again, every user will get the same factsheet, just you save yourself having to update it manually each time the input data changes.

The hrefs look similar to the public case, though we will source the data differently, generating it in the non-HTML resource route:

src/pages/index.astro
astro
    
1 <!-- TRUNCATED -->
2 <body>
3 <main class="wrapper">
4 <h1>Astro JS non-HTML Routes</h1>
5 <ul>
6 <li><a aria-label="Open P D F file" href="/pdf-resource.pdf">PDF file Route</a></li>
7 <li><a aria-label="Open J S O N file" href="/json-resource.json">JSON file Route</a></li>
8 </ul>
9 </main>
10 </body>
11 </html>

Server Side Rendered (SSR) API Route #

If you want to go to town and have an SSR Astro site, you can opt for a similar approach, not too different from what we do here. In this case, you could even personalize, the factsheet, adding the visitor’s name at the top of it. We will see only a small couple of changes are needed to generate the PDF on an SSR site (compared to a static one). In reality, the biggest difference is that you need a form or some other mechanism for collection user personalized data.

📝 Astro PDF File Route on Static Site #

To create a non-HTML route in Astro for a static site, you add a new file in src/pages. Similar to file-based routing for HTML pages, the path will mirror the href you access the file with. The only difference is that you will add .js or .ts on the end. So in our snippet above, where the href is /pdf-resource.pdf our full path for the resource route will be src/pages/pdf-resource.pdf.ts (we will use TypeScript).

Here’s the file:

src/pages/pdf-resource.pdf.ts
typescript
    
1 import type { APIRoute } from 'astro';
2 import pdf from 'pdfjs';
3 import helvetica from 'pdfjs/font/Helvetica';
4
5 export const GET: APIRoute = async function GET() {
6 try {
7 const doc = new pdf.Document({ font: helvetica, padding: 10 });
8 const text = doc.text({ fontSize: 12 });
9 text.add('Example PDF');
10 const buffer = await doc.asBuffer();
11
12 return new Response(buffer.toString('binary'), {
13 headers: {
14 'Content-Type': 'application/pdf',
15 },
16 });
17 } catch (error: unknown) {
18 throw new Error(`Something went wrong in pdf-resource.pdf route!: ${error as string}`);
19 }
20 };

We use the pdfjs package here to generate the PDF for us. It just has dummy content in our case. You might generate it from scratch, or compose it from other PDFs in your real-world app. See more on pdfjs usage in the docs . Note, in line 12, we return a Response object. The data will be binary encoded, in this case, with an application/pdf MIME type.

Remember, building a static site, this file will only change when you rebuild the site. This is fine if you do not need to customize it for each visitor.

blurry low resolution placeholder image Astro JS non-HTML Routes: screenshot of P D F route. Shows a P D F file open in a browser at route /pdf-resources.pdf. The file contains the text Example P D F
Astro JS non-HTML Routes: Static PDF Example

SSR Extension #

For SSR, nothing much changes, just that, now, we can send a 501 server error response code when something goes wrong on a particular request:

src/pages/pdf-resource.ts
typescript
    
import type { APIRoute } from 'astro';
import pdf from 'pdfjs';
import helvetica from 'pdfjs/font/Helvetica';
export const GET: APIRoute = async function GET() {
try {
const doc = new pdf.Document({ font: helvetica, padding: 10 });
const text = doc.text({ fontSize: 12 });
text.add('Example PDF');
const buffer = await doc.asBuffer();
return new Response(buffer.toString('binary'), {
headers: {
'Content-Type': 'application/pdf',
},
});
} catch (error: unknown) {
return new Response(`Something went wrong in pdf-resource.pdf route!: ${error as string}`, {
status: 501,
statusText: 'Server error',
});
}
};

We are also free to customize the output here for every request.

🤖 Astro JSON Resource Route on Static Site #

    
import type { APIRoute } from 'astro';
export const GET: APIRoute = async function GET() {
try {
const astroResources = [
{ name: 'docs', url: 'https://docs.astro.build/en/getting-started/' },
{ name: 'discord', url: 'https://docs.astro.build/chat' },
];
return new Response(JSON.stringify(astroResources), {
headers: {
'Content-Type': 'application/json',
},
});
} catch (error) {
throw new Error('Something went wrong in json-resource.json route!');
}
};

Here, we build the JSON within the file. Again, for a static site, we can customize per-build, but have to go full SSR to customize per-request. Like for the PDF route, if we do go SSR, we can drop the .json extension (going for json-resource.ts instead).

blurry low resolution placeholder image Astro JS non-HTML Routes: screenshot of J S O N route. The screenshot show JSON browser in Firefox. There is an array of two objects.  The U R L is localhost: 3001/json-resource.json
Astro JS non-HTML Routes: Static JSON Example

🗳 Poll #

What will your next File route be?
Voting reveals latest results.

🙌🏽 Astro JS non‑HTML Routes: Wrapping Up #

In this Astro JS non-HTML routes post, we have had a look at serving files or resources from API routes. In particular, we saw:

  • how to serve PDFs and JSON data from static file routes;
  • an example generating a PDF resource in an SSR API route; and
  • when you can avoid these techniques and go for something simpler.

Hope you have found this post useful! As always, there are a lot of ways in which you can level up. You can adapt the code to generate a CSV file on your static or SSR Astro site. You could explore pdfjs and generate a full-featured PDF for your app. If you want to go next-level, consider adding a Webhook listener, for example, which listens for a Webhook from one service and triggers a Webhook on another (like rebuilding your static Astro site)! You could also generate Open Graph social sharing images. Whatever you opt for, have a look at the full project code on the Rodney Lab GitHub page . I am keen to hear how you will the starter on your own projects as well as possible improvements.

🏁 Astro JS non‑HTML Routes: Summary #

Can Astro sites serve non-HTML files? #

Yes, we are talking about file routes or resource routes here. Just like HTML routes, the files which generate these sit in the `src/pages` folder of your Astro project. Common examples are serving a PDF file or JSON data, though you are by no means limited to those. The sky is the limit! For the PDF file on a static Astro site, you just generate the file content in a JavaScript file named, for example, `src/pages/datasheet.pdf.js`. This will be accessible from the `https://example.com/datasheet.pdf` href on the final site. In that file, you will want to return an object with a `body` field. The value of that field will be a string set to the PDF file content. For an SSR site, name the file `src/pages/datasheet.js`. Now you will return an HTTP Response object. You can add a content-type header of `application/pdf`.

Do you need a resource route to serve a static JSON file with Astro? #

No, is the short answer! A great example is the manifest.json file which contains info on your site’s favicon and other data used in Progressive Web Apps. Typically, this file will not change often and does not need processing by Vite (Astro’s bundler). You can just place the manifest.json file in the `public` folder of your project. If you wanted to serve a more dynamic JSON file. Let’s say you need to pull in fresh data on each build to form the JSON file. Here you might as well make use of Vite and create a resource route. We have seen this is not too difficult to do. You could even make the site Server-Side Rendered and customize the JSON data for each visitor, pulling in real-time data.

Can you use Astro to generate a PDF? #

Astro is great for content sites, and it is super common to serve PDFs on content sites. So we are in luck that you can create a PDF on a file route in Astro. We saw an example using pdfjs. But you might also consider pdfkit or even React PDF Renderer. Whatever you opt for, bear in mind if you go for creating a static Astro site, the content will only be refreshed each time you rebuild your site. This will work just fine for a lot of use cases. If you need something more dynamic though, pull SSR out of the Astro toolbox!

🙏🏽 Astro JS non‑HTML Routes: Feedback #

Have you found the post useful? Would you prefer to see posts on another topic instead? Get in touch with ideas for new posts. Also, if you like my writing style, get in touch if I can write some posts for your company site on a consultancy basis. Read on to find ways to get in touch, further below. If you want to support posts similar to this one and can spare a few dollars, euros or pounds, please consider supporting me through Buy me a Coffee.

blurry low resolution placeholder image ask Rodney X (formerly Twitter) avatar

Rodney

@askRodney

Just dropped a new post about using file routes or resource routes in 🚀 Astro.

We see a JSON example as well as the PDF and also touch on SSR and alternatives, though you might try Webhooks too.

Hope you find it useful!

#simplytheastro #askRodneyhttps://t.co/a24SOi00gg

— Rodney (@askRodney) August 24, 2022

Finally, feel free to share the post on your social media accounts for all your followers who will find it useful. As well as leaving a comment below, you can get in touch via @askRodney on Twitter and also askRodney on Telegram . Also, see further ways to get in touch with Rodney Lab. I post regularly on Astro as well as SvelteKit. Also, subscribe to the newsletter to keep up-to-date with our latest projects.

Thanks for reading this post. I hope you found it valuable. Please get in touch with your feedback and suggestions for posts you would like to see. Read more about me …

blurry low resolution placeholder image Rodney from Rodney Lab
TAGS:
ASTRO

Related Posts

blurry low resolution placeholder image Astro Server-Side Rendering: Edge Search Site

Astro Server-Side Rendering: Edge Search Site

plus
astro
<PREVIOUS POST
NEXT POST >
LATEST POST >>

Leave a comment …

Your information will be handled in line with our Privacy Policy .

Comments

  • Andrew Wooldridge

    Thank you so much for writing this post! It helped me quite a bit!

    2 years ago
  • Mike

    Worked perfectly thank you!

    2 years ago

Ask for more

1 Nov 2022 — Astro Server-Side Rendering: Edge Search Site
3 Oct 2022 — Svelte eCommerce Site: SvelteKit Snipcart Storefront
1 Sept 2022 — Get Started with SvelteKit Headless WordPress

Copyright © 2020 – 2025 Rodney Johnson. All Rights Reserved. Please read important copyright and intellectual property information.

  • Home
  • Profile
  • Plus +
  • Newsletter
  • Contact
  • Links
  • Terms of Use
  • Privacy Policy
We use cookies  to enhance visitors’ experience. Please click the “Options” button to make your choice.  Learn more here.