├── src ├── components │ ├── AdComponent.astro │ ├── Pagination.astro │ ├── table │ │ ├── Head.astro │ │ ├── Cell.astro │ │ └── Table.astro │ ├── Search.astro │ ├── Footer.jsx │ ├── NestedList.astro │ ├── Card.astro │ ├── Accordion.astro │ ├── Form.jsx │ └── SearchModal.astro ├── assets │ ├── img │ │ ├── cooking.png │ │ ├── credits.png │ │ ├── logo-nms.png │ │ ├── refining.png │ │ ├── crafting-guide.png │ │ └── logo.svg │ └── css │ │ ├── main.css │ │ └── tabulator.css ├── env.d.ts ├── utils │ ├── classNames.js │ └── lookup.ts ├── pages │ ├── feedback.astro │ ├── fish │ │ ├── [id].astro │ │ └── [page].astro │ ├── curiosities │ │ ├── [id].astro │ │ └── [page].astro │ ├── cooking │ │ ├── [id].astro │ │ ├── index.astro │ │ └── cards │ │ │ └── index.astro │ ├── raw │ │ ├── [id].astro │ │ └── [page].astro │ ├── products │ │ ├── [id].astro │ │ └── [page].astro │ ├── other │ │ ├── [id].astro │ │ └── [page].astro │ ├── buildings │ │ ├── [id].astro │ │ └── [page].astro │ ├── technology │ │ ├── [id].astro │ │ └── [page].astro │ ├── search.json.ts │ ├── calculator │ │ └── [page].astro │ ├── all-items │ │ └── [page].astro │ ├── crafting-guide │ │ ├── index.astro │ │ └── cards │ │ │ └── index.astro │ ├── refining │ │ ├── index.astro │ │ └── cards │ │ │ └── index.astro │ ├── index.astro │ ├── privacy.astro │ └── privacy-policy.astro ├── config.ts ├── data │ ├── index.ts │ ├── getFish.py │ └── Trade.json └── layouts │ ├── Layout.astro │ ├── Sidebar.jsx │ └── Page.astro ├── public ├── ads.txt ├── images │ ├── icon.png │ ├── cooker.webp │ ├── logo-nms.png │ ├── refiner.webp │ ├── calculator.webp │ ├── crafting.webp │ ├── logo-nms.webp │ ├── resources.png │ └── backgrounds │ │ ├── bg1.webp │ │ ├── bg2.webp │ │ ├── bg3.webp │ │ ├── bg4.webp │ │ ├── bg5.webp │ │ ├── bg6.webp │ │ ├── bg7.webp │ │ ├── bg8.webp │ │ ├── bg9.webp │ │ ├── bg10.webp │ │ ├── bg11.webp │ │ ├── bg12.webp │ │ └── bg13.webp ├── fonts │ ├── FuturaProBook.woff │ └── FuturaProBook.woff2 └── favicon.svg ├── .vscode └── extensions.json ├── tsconfig.json ├── .gitignore ├── astro.config.mjs ├── tailwind.config.cjs ├── package.json ├── vercel.json └── README.md /src/components/AdComponent.astro: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/ads.txt: -------------------------------------------------------------------------------- 1 | google.com, pub-8524094599848175, DIRECT, f08c47fec0942fa0 -------------------------------------------------------------------------------- /public/images/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bradhave94/nms/HEAD/public/images/icon.png -------------------------------------------------------------------------------- /public/images/cooker.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bradhave94/nms/HEAD/public/images/cooker.webp -------------------------------------------------------------------------------- /public/images/logo-nms.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bradhave94/nms/HEAD/public/images/logo-nms.png -------------------------------------------------------------------------------- /public/images/refiner.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bradhave94/nms/HEAD/public/images/refiner.webp -------------------------------------------------------------------------------- /src/assets/img/cooking.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bradhave94/nms/HEAD/src/assets/img/cooking.png -------------------------------------------------------------------------------- /src/assets/img/credits.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bradhave94/nms/HEAD/src/assets/img/credits.png -------------------------------------------------------------------------------- /public/images/calculator.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bradhave94/nms/HEAD/public/images/calculator.webp -------------------------------------------------------------------------------- /public/images/crafting.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bradhave94/nms/HEAD/public/images/crafting.webp -------------------------------------------------------------------------------- /public/images/logo-nms.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bradhave94/nms/HEAD/public/images/logo-nms.webp -------------------------------------------------------------------------------- /public/images/resources.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bradhave94/nms/HEAD/public/images/resources.png -------------------------------------------------------------------------------- /src/assets/img/logo-nms.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bradhave94/nms/HEAD/src/assets/img/logo-nms.png -------------------------------------------------------------------------------- /src/assets/img/refining.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bradhave94/nms/HEAD/src/assets/img/refining.png -------------------------------------------------------------------------------- /src/env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | /// 3 | -------------------------------------------------------------------------------- /public/fonts/FuturaProBook.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bradhave94/nms/HEAD/public/fonts/FuturaProBook.woff -------------------------------------------------------------------------------- /public/fonts/FuturaProBook.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bradhave94/nms/HEAD/public/fonts/FuturaProBook.woff2 -------------------------------------------------------------------------------- /public/images/backgrounds/bg1.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bradhave94/nms/HEAD/public/images/backgrounds/bg1.webp -------------------------------------------------------------------------------- /public/images/backgrounds/bg2.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bradhave94/nms/HEAD/public/images/backgrounds/bg2.webp -------------------------------------------------------------------------------- /public/images/backgrounds/bg3.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bradhave94/nms/HEAD/public/images/backgrounds/bg3.webp -------------------------------------------------------------------------------- /public/images/backgrounds/bg4.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bradhave94/nms/HEAD/public/images/backgrounds/bg4.webp -------------------------------------------------------------------------------- /public/images/backgrounds/bg5.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bradhave94/nms/HEAD/public/images/backgrounds/bg5.webp -------------------------------------------------------------------------------- /public/images/backgrounds/bg6.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bradhave94/nms/HEAD/public/images/backgrounds/bg6.webp -------------------------------------------------------------------------------- /public/images/backgrounds/bg7.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bradhave94/nms/HEAD/public/images/backgrounds/bg7.webp -------------------------------------------------------------------------------- /public/images/backgrounds/bg8.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bradhave94/nms/HEAD/public/images/backgrounds/bg8.webp -------------------------------------------------------------------------------- /public/images/backgrounds/bg9.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bradhave94/nms/HEAD/public/images/backgrounds/bg9.webp -------------------------------------------------------------------------------- /src/assets/img/crafting-guide.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bradhave94/nms/HEAD/src/assets/img/crafting-guide.png -------------------------------------------------------------------------------- /public/images/backgrounds/bg10.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bradhave94/nms/HEAD/public/images/backgrounds/bg10.webp -------------------------------------------------------------------------------- /public/images/backgrounds/bg11.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bradhave94/nms/HEAD/public/images/backgrounds/bg11.webp -------------------------------------------------------------------------------- /public/images/backgrounds/bg12.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bradhave94/nms/HEAD/public/images/backgrounds/bg12.webp -------------------------------------------------------------------------------- /public/images/backgrounds/bg13.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bradhave94/nms/HEAD/public/images/backgrounds/bg13.webp -------------------------------------------------------------------------------- /src/utils/classNames.js: -------------------------------------------------------------------------------- 1 | export function classNames(...classes) { 2 | return classes.filter(Boolean).join(' '); 3 | } -------------------------------------------------------------------------------- /.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": ["astro-build.astro-vscode"], 3 | "unwantedRecommendations": [] 4 | } 5 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "astro/tsconfigs/base", 3 | "compilerOptions": { 4 | "baseUrl": ".", 5 | "paths": { 6 | "@*": ["./src/*"] 7 | } 8 | } 9 | } -------------------------------------------------------------------------------- /src/pages/feedback.astro: -------------------------------------------------------------------------------- 1 | --- 2 | import Layout from '../layouts/Layout.astro'; 3 | import Form from '../components/Form.jsx'; 4 | --- 5 | 6 | 11 |
12 | 13 | -------------------------------------------------------------------------------- /src/components/Pagination.astro: -------------------------------------------------------------------------------- 1 | --- 2 | const { page } = Astro.props; 3 | --- 4 | 5 |
6 | {page.url.prev && Previous} 7 | Page: {page.currentPage} of {page.lastPage} 8 | {page.url.next && Next} 9 |
-------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # build output 2 | dist/ 3 | .output/ 4 | # generated types 5 | .astro/ 6 | 7 | # dependencies 8 | node_modules/ 9 | 10 | # logs 11 | npm-debug.log* 12 | yarn-debug.log* 13 | yarn-error.log* 14 | pnpm-debug.log* 15 | 16 | 17 | # environment variables 18 | .env 19 | .env.production 20 | 21 | # macOS-specific files 22 | .DS_Store 23 | -------------------------------------------------------------------------------- /astro.config.mjs: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'astro/config'; 2 | import sitemap from "@astrojs/sitemap"; 3 | import tailwind from "@astrojs/tailwind"; 4 | 5 | import react from "@astrojs/react"; 6 | 7 | // https://astro.build/config 8 | export default defineConfig({ 9 | site: "https://nms.vercel.app/", 10 | integrations: [ react(), sitemap(), tailwind({ 11 | config: { 12 | applyBaseStyles: false 13 | } 14 | })] 15 | }); -------------------------------------------------------------------------------- /src/components/table/Head.astro: -------------------------------------------------------------------------------- 1 | --- 2 | export interface Props { 3 | columns: Array<{ 4 | title: string; 5 | field: string; 6 | }>; 7 | } 8 | 9 | const { columns } = Astro.props; 10 | --- 11 | 12 | 13 | 14 | {columns.map((column) => ( 15 | {column.title} 16 | ))} 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /src/config.ts: -------------------------------------------------------------------------------- 1 | export const SITE = { 2 | website: "https://nomansskyrecipes.com", 3 | author: "Bradley Haveman", 4 | desc: "Unlock new possibilities in No Man's Sky with our comprehensive list of in game items and recipes. From rare resources to exotic ingredients, our guide has everything you need to take your game to the next level. Discover the secrets of the universe today!", 5 | title: "No Man's Sky Recipes", 6 | version: 6.0, 7 | version_name: "Boyagers", 8 | version_link: "https://www.nomanssky.com/voyagers-update", 9 | adsense_id: 'ca-pub-8524094599848175', 10 | }; -------------------------------------------------------------------------------- /tailwind.config.cjs: -------------------------------------------------------------------------------- 1 | /** @type {import('tailwindcss').Config} */ 2 | const colors = require('tailwindcss/colors'); 3 | module.exports = { 4 | content: ['./src/**/*.{astro,html,js,jsx,md,mdx,svelte,ts,tsx,vue}'], 5 | theme: { 6 | fontFamily: { 7 | 'nms': ['"FuturaProBook", sans-serif'] 8 | }, 9 | extend: { 10 | colors: { 11 | 'warm-gray': colors.stone, 12 | teal: colors.teal, 13 | sky: colors.sky, 14 | teal: colors.teal, 15 | rose: colors.rose, 16 | }, 17 | }, 18 | }, 19 | plugins: [require('@tailwindcss/forms'), require('@tailwindcss/aspect-ratio')], 20 | }; 21 | -------------------------------------------------------------------------------- /src/pages/fish/[id].astro: -------------------------------------------------------------------------------- 1 | --- 2 | import Layout from '@layouts/Layout.astro'; 3 | import Page from '@layouts/Page.astro'; 4 | import data from '@data/Fish.json'; 5 | 6 | export async function getStaticPaths() { 7 | return data.map((post) => ({ 8 | params: { id: post.fishId.toString() }, 9 | props: { item: post }, 10 | })); 11 | } 12 | 13 | const { item } = Astro.props; 14 | 15 | const title = `${item.Name} | No Man's Sky Recipes`; 16 | const description = `${item.Name} | ${item.Description}`; 17 | --- 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /src/pages/curiosities/[id].astro: -------------------------------------------------------------------------------- 1 | --- 2 | import Layout from '@layouts/Layout.astro'; 3 | import Page from '@layouts/Page.astro'; 4 | import data from '@data/Curiosities.json'; 5 | 6 | export async function getStaticPaths() { 7 | return data.map((post) => ({ 8 | params: { id: post.Id.toString() }, 9 | props: { item: post }, 10 | })); 11 | } 12 | 13 | const { item } = Astro.props; 14 | 15 | const title = `${item.Name} | No Man's Sky Recipes`; 16 | const description = `${item.Name} | ${item.Description}`; 17 | --- 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /src/pages/cooking/[id].astro: -------------------------------------------------------------------------------- 1 | --- 2 | import Layout from '@layouts/Layout.astro'; 3 | import Page from '@layouts/Page.astro'; 4 | import type { Item } from '@utils/lookup.js'; 5 | import data from '@data/Cooking.json'; 6 | 7 | export async function getStaticPaths() { 8 | return data.map((post) => ({ 9 | params: { id: post.Id.toString() }, 10 | props: { item: post }, 11 | })); 12 | } 13 | 14 | const { item } = Astro.props; 15 | 16 | const title = `${item.Name} | No Man's Sky Recipes`; 17 | const description = `${item.Name} | ${item.Description}`; 18 | --- 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /src/pages/raw/[id].astro: -------------------------------------------------------------------------------- 1 | --- 2 | import Layout from '@layouts/Layout.astro'; 3 | import Page from '@layouts/Page.astro'; 4 | import type { Item } from '@utils/lookup.js'; 5 | import data from '@data/RawMaterials.json'; 6 | 7 | export async function getStaticPaths() { 8 | return data.map((post) => ({ 9 | params: { id: post.Id.toString() }, 10 | props: { item: post }, 11 | })); 12 | } 13 | 14 | const { item } = Astro.props; 15 | 16 | const title = `${item.Name} | No Man's Sky Recipes`; 17 | const description = `${item.Name} | ${item.Description}`; 18 | --- 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /src/pages/products/[id].astro: -------------------------------------------------------------------------------- 1 | --- 2 | import Layout from '@layouts/Layout.astro'; 3 | import Page from '@layouts/Page.astro'; 4 | import type { Item } from '@utils/lookup.js'; 5 | import data from '@data/Products.json'; 6 | 7 | export async function getStaticPaths() { 8 | return data.map((product) => ({ 9 | params: { id: product.Id.toString() }, 10 | props: { item: product }, 11 | })); 12 | } 13 | 14 | const { item } = Astro.props; 15 | 16 | const title = `${item.Name} | No Man's Sky Recipes`; 17 | const description = `${item.Name} | ${item.Description}`; 18 | --- 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /src/pages/other/[id].astro: -------------------------------------------------------------------------------- 1 | --- 2 | import Layout from '@layouts/Layout.astro'; 3 | import Page from '@layouts/Page.astro'; 4 | import type { Item } from '@utils/lookup.js'; 5 | import others from '@data/Others.json'; 6 | import trade from '@data/Trade.json'; 7 | 8 | export async function getStaticPaths() { 9 | return [...others, ...trade].map((post) => ({ 10 | params: { id: post.Id.toString() }, 11 | props: { item: post }, 12 | })); 13 | } 14 | 15 | const { item } = Astro.props; 16 | --- 17 | 18 | 23 | 24 | -------------------------------------------------------------------------------- /src/pages/buildings/[id].astro: -------------------------------------------------------------------------------- 1 | --- 2 | import Layout from '@layouts/Layout.astro'; 3 | import Page from '@layouts/Page.astro'; 4 | import { getById } from '@utils/lookup.js'; 5 | import type { Item } from '@utils/lookup.js'; 6 | import buildings from '@data/Buildings.json'; 7 | 8 | export function getStaticPaths() { 9 | return buildings.map((building) => ({ 10 | params: { id: building.Id.toString() } 11 | })); 12 | } 13 | 14 | const { id } = Astro.params; 15 | const item = getById(id); 16 | 17 | if (!item) { 18 | return Astro.redirect('/404'); 19 | } 20 | 21 | const { Name, Description } = item; 22 | --- 23 | 24 | 29 | 30 | -------------------------------------------------------------------------------- /src/data/index.ts: -------------------------------------------------------------------------------- 1 | export { default as Buildings } from './Buildings.json'; 2 | export { default as ConstructedTechnology } from './ConstructedTechnology.json'; 3 | export { default as Cooking } from './Cooking.json'; 4 | export { default as Curiosities } from './Curiosities.json'; 5 | export { default as NutrientProcessor } from './NutrientProcessor.json'; 6 | export { default as Others } from './Others.json'; 7 | export { default as Products } from './Products.json'; 8 | export { default as RawMaterials } from './RawMaterials.json'; 9 | export { default as Refinery } from './Refinery.json'; 10 | export { default as Technology } from './Technology.json'; 11 | export { default as TechnologyModule } from './TechnologyModule.json'; 12 | export { default as Trade } from './Trade.json'; 13 | export { default as Fish } from './Fish.json'; -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@nomansskyrecipes", 3 | "type": "module", 4 | "version": "5.7.0", 5 | "private": true, 6 | "scripts": { 7 | "dev": "astro dev", 8 | "start": "astro dev", 9 | "build": "astro build", 10 | "preview": "astro preview", 11 | "astro": "astro" 12 | }, 13 | "dependencies": { 14 | "@astrojs/react": "^4.3.0", 15 | "@astrojs/sitemap": "^3.4.1", 16 | "@astrojs/tailwind": "^6.0.2", 17 | "@headlessui/react": "^1.7.10", 18 | "@heroicons/react": "^2.0.15", 19 | "@types/react": "^18.0.28", 20 | "@types/react-dom": "^18.0.10", 21 | "@vercel/analytics": "^0.1.10", 22 | "astro": "^5.10.1", 23 | "react": "^18.2.0", 24 | "react-dom": "^18.2.0", 25 | "tabulator-tables": "^5.4.3", 26 | "tailwindcss": "^3.2.6" 27 | }, 28 | "devDependencies": { 29 | "@tailwindcss/aspect-ratio": "^0.4.2", 30 | "@tailwindcss/forms": "^0.5.3" 31 | } 32 | } -------------------------------------------------------------------------------- /public/favicon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 13 | 14 | -------------------------------------------------------------------------------- /src/assets/img/logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /src/pages/technology/[id].astro: -------------------------------------------------------------------------------- 1 | --- 2 | import Layout from '@layouts/Layout.astro'; 3 | import Page from '@layouts/Page.astro'; 4 | import { sort } from '@utils/lookup.js'; 5 | import type { Item } from '@utils/lookup.js'; 6 | import * as dataSources from '@data/index'; 7 | 8 | export async function getStaticPaths() { 9 | // Combine all technology types into a single array 10 | const allTech: Item[] = [ 11 | ...dataSources.ConstructedTechnology, 12 | ...dataSources.Technology, 13 | ...dataSources.TechnologyModule 14 | ] as Item[]; 15 | 16 | const sortedTech = sort(allTech); 17 | return sortedTech.map((post) => ({ 18 | params: { id: post.Id.toString() }, 19 | props: { item: post }, 20 | })); 21 | } 22 | 23 | interface Props { 24 | item: Item; 25 | } 26 | 27 | const { item } = Astro.props; 28 | 29 | if (!item) { 30 | return Astro.redirect('/404'); 31 | } 32 | --- 33 | 34 | 39 | 40 | -------------------------------------------------------------------------------- /vercel.json: -------------------------------------------------------------------------------- 1 | { 2 | "redirects": [ 3 | { "source": "/portable-refiner", "destination": "/refining", "permanent": true }, 4 | { "source": "/medium-refiner", "destination": "/refining", "permanent": true }, 5 | { "source": "/large-refiner", "destination": "/refining", "permanent": true }, 6 | { "source": "/all", "destination": "/refining", "permanent": true }, 7 | { "source": "/buildings", "destination": "/buildings/1", "permanent": true }, 8 | { "source": "/all-items", "destination": "/all-items/1", "permanent": true }, 9 | { "source": "/raw", "destination": "/raw/1", "permanent": true }, 10 | { "source": "/other", "destination": "/other/1", "permanent": true }, 11 | { "source": "/curiosities", "destination": "/curiosities/1", "permanent": true }, 12 | { "source": "/fish", "destination": "/fish/1", "permanent": true }, 13 | { "source": "/technology", "destination": "/technology/1", "permanent": true }, 14 | { "source": "/products", "destination": "/products/1", "permanent": true }, 15 | { "source": "/calculator", "destination": "/calculator/1", "permanent": true }, 16 | { "source": "/sitemap", "destination": "/sitemap-0.xml", "permanent": true } 17 | ] 18 | } 19 | -------------------------------------------------------------------------------- /src/pages/search.json.ts: -------------------------------------------------------------------------------- 1 | import type { APIRoute } from 'astro'; 2 | import { getLabel, getSlug, sort } from '@utils/lookup.js'; 3 | import * as dataSources from '@data/index'; 4 | 5 | // Combine and sort all data 6 | const data = sort( 7 | Object.values(dataSources).flatMap(source => 8 | source.map(item => ({ 9 | ...item, 10 | CraftingOutputAmount: item.CraftingOutputAmount || undefined 11 | })) 12 | ) 13 | ); 14 | 15 | // Create search data 16 | const search = data.map((item) => ({ 17 | id: item.fishId || item.Id, 18 | name: item.Name, 19 | type: getLabel(item.Id), 20 | url: `/${getSlug(item.Id)}/${item.fishId || item.Id}`.replace(/\/+/g, '/'), 21 | })); 22 | 23 | export const GET: APIRoute = ({ request }) => { 24 | const url = new URL(request.url); 25 | const query = url.searchParams.get('q')?.toLowerCase(); 26 | 27 | const results = query 28 | ? search.filter(item => 29 | item.name.toLowerCase().includes(query) || 30 | item.type.toLowerCase().includes(query) 31 | ) 32 | : search; 33 | 34 | return new Response( 35 | JSON.stringify({ body: results }), 36 | { 37 | headers: { 38 | 'Content-Type': 'application/json', 39 | 'Cache-Control': 'public, max-age=3600', // Cache for 1 hour 40 | }, 41 | } 42 | ); 43 | }; -------------------------------------------------------------------------------- /src/pages/fish/[page].astro: -------------------------------------------------------------------------------- 1 | --- 2 | import Layout from '@layouts/Layout.astro'; 3 | import Card from '@components/Card.astro'; 4 | import { getSlug, sort } from '@utils/lookup.js'; 5 | import data from '@data/Fish.json'; 6 | import Pagination from '@components/Pagination.astro'; 7 | 8 | export async function getStaticPaths({ paginate }) { 9 | return paginate(sort(data), { pageSize: 24 }); 10 | } 11 | // All paginated data is passed on the "page" prop 12 | const { page } = Astro.props; 13 | --- 14 | 15 | 20 |

Fish

21 |
22 | { 23 | page.data.map((item, index) => ( 24 | 35 | )) 36 | } 37 |
38 | 39 | 40 |
41 | -------------------------------------------------------------------------------- /src/pages/products/[page].astro: -------------------------------------------------------------------------------- 1 | --- 2 | import Layout from '@layouts/Layout.astro'; 3 | import Card from '@components/Card.astro'; 4 | import Pagination from '@components/Pagination.astro'; 5 | import { getSlug, sort } from '@utils/lookup.js'; 6 | import data from '@data/Products.json'; 7 | export async function getStaticPaths({ paginate }) { 8 | return paginate(sort(data), { pageSize: 24 }); 9 | } 10 | // All paginated data is passed on the "page" prop 11 | const { page } = Astro.props; 12 | --- 13 | 14 | 19 |

Products

20 |
21 | { 22 | page.data.map((item, index) => ( 23 | 34 | )) 35 | } 36 |
37 | 38 |
39 | -------------------------------------------------------------------------------- /src/pages/other/[page].astro: -------------------------------------------------------------------------------- 1 | --- 2 | import Layout from '@layouts/Layout.astro'; 3 | import Card from '@components/Card.astro'; 4 | import Pagination from '@components/Pagination.astro'; // New import 5 | import { getSlug, sort } from '@utils/lookup.js'; 6 | import others from '@data/Others.json'; 7 | import trade from '@data/Trade.json'; 8 | 9 | export async function getStaticPaths({ paginate }) { 10 | return paginate(sort([...others, ...trade]), { pageSize: 24 }); 11 | } 12 | 13 | const { page } = Astro.props; 14 | --- 15 | 16 | 21 |

Other Items

22 |
23 | { 24 | page.data.map((item) => ( 25 | 35 | )) 36 | } 37 |
38 | 39 |
-------------------------------------------------------------------------------- /src/pages/raw/[page].astro: -------------------------------------------------------------------------------- 1 | --- 2 | import Layout from '@layouts/Layout.astro'; 3 | import Card from '@components/Card.astro'; 4 | import Pagination from '@components/Pagination.astro'; 5 | import { getSlug, sort } from '@utils/lookup.js'; 6 | import data from '@data/RawMaterials.json'; 7 | 8 | export async function getStaticPaths({ paginate }) { 9 | return paginate(sort(data), { pageSize: 24 }); 10 | } 11 | // All paginated data is passed on the "page" prop 12 | const { page } = Astro.props; 13 | --- 14 | 15 | 20 |

Raw Materials

21 |
22 | { 23 | page.data.map((item, index) => ( 24 | 35 | )) 36 | } 37 |
38 | 39 |
40 | -------------------------------------------------------------------------------- /src/pages/buildings/[page].astro: -------------------------------------------------------------------------------- 1 | --- 2 | import Layout from '@layouts/Layout.astro'; 3 | import Card from '@components/Card.astro'; 4 | import Pagination from '@components/Pagination.astro'; 5 | import { getSlug, sort } from '@utils/lookup.js'; 6 | import data from '@data/Buildings.json'; 7 | 8 | export async function getStaticPaths({ paginate }) { 9 | return paginate(sort(data), { pageSize: 24 }); 10 | } 11 | // All paginated data is passed on the "page" prop 12 | const { page } = Astro.props; 13 | --- 14 | 15 | 20 |

Building Parts

21 |
22 | { 23 | page.data.map((item, index) => ( 24 | 35 | )) 36 | } 37 |
38 | 39 |
40 | -------------------------------------------------------------------------------- /src/pages/curiosities/[page].astro: -------------------------------------------------------------------------------- 1 | --- 2 | import Layout from '@layouts/Layout.astro'; 3 | import Card from '@components/Card.astro'; 4 | import { getSlug, sort } from '@utils/lookup.js'; 5 | import data from '@data/Curiosities.json'; 6 | import Pagination from '@components/Pagination.astro'; 7 | 8 | export async function getStaticPaths({ paginate }) { 9 | return paginate(sort(data), { pageSize: 24 }); 10 | } 11 | // All paginated data is passed on the "page" prop 12 | const { page } = Astro.props; 13 | --- 14 | 15 | 20 |

Curiosities

21 |
22 | { 23 | page.data.map((item, index) => ( 24 | 35 | )) 36 | } 37 |
38 | 39 | 40 |
41 | -------------------------------------------------------------------------------- /src/pages/technology/[page].astro: -------------------------------------------------------------------------------- 1 | --- 2 | import Layout from '@layouts/Layout.astro'; 3 | import Card from '@components/Card.astro'; 4 | import Pagination from '@components/Pagination.astro'; 5 | import { getSlug, sort } from '@utils/lookup.js'; 6 | import conTech from '@data/ConstructedTechnology.json'; 7 | import techModule from '@data/TechnologyModule.json'; 8 | import tech from '@data/Technology.json'; 9 | 10 | export async function getStaticPaths({ paginate }) { 11 | return paginate(sort([...conTech, ...tech, ...techModule]), { pageSize: 24 }); 12 | } 13 | // All paginated data is passed on the "page" prop 14 | const { page } = Astro.props; 15 | --- 16 | 17 | 22 |

Technology

23 |
24 | { 25 | page.data.map((item, index) => ( 26 | 37 | )) 38 | } 39 |
40 | 41 |
42 | -------------------------------------------------------------------------------- /src/pages/calculator/[page].astro: -------------------------------------------------------------------------------- 1 | --- 2 | import Layout from '@layouts/Layout.astro'; 3 | import Card from '@components/Card.astro'; 4 | import Pagination from '@components/Pagination.astro'; 5 | import { getSlug, sort } from '@utils/lookup.js'; 6 | import data from '@data/Products.json'; 7 | 8 | export async function getStaticPaths({ paginate }) { 9 | return paginate(data.sort((a, b) => b.BaseValueUnits - a.BaseValueUnits), { pageSize: 24 }); 10 | } 11 | // All paginated data is passed on the "page" prop 12 | const { page } = Astro.props; 13 | --- 14 | 15 | 20 |

Crafting Calculator

21 |

Choose an item below to start

22 |
23 | { 24 | page.data.map((item) => 25 | item.RequiredItems.length > 0 ? ( 26 | 36 | ) : null 37 | ) 38 | } 39 |
40 | 41 |
42 | -------------------------------------------------------------------------------- /src/components/Search.astro: -------------------------------------------------------------------------------- 1 | 14 | 15 | -------------------------------------------------------------------------------- /src/data/getFish.py: -------------------------------------------------------------------------------- 1 | import json 2 | 3 | def extract_fish(): 4 | # Read the Curiosities.json file 5 | with open('./Curiosities.json', 'r') as file: 6 | curiosities = json.load(file) 7 | 8 | # Initialize lists for fish and non-fish items 9 | fish_items = [] 10 | non_fish_items = [] 11 | unique_groups = set() 12 | 13 | # Separate fish from non-fish items 14 | for item in curiosities: 15 | group = item.get('Group', '') 16 | unique_groups.add(group) 17 | if 'Fish' in group and group != "Fishing Bait": 18 | fish_items.append(item) 19 | else: 20 | non_fish_items.append(item) 21 | 22 | # Print unique groups 23 | print("Unique Groups found:") 24 | for group in sorted(unique_groups): 25 | print(f"- {group}") 26 | 27 | # Sort fish items alphabetically by name 28 | fish_items.sort(key=lambda x: x.get('Name', '').lower()) 29 | 30 | # Add the fishId field to fish items 31 | for index, item in enumerate(fish_items, start=1): 32 | item['fishId'] = f'fish{index}' 33 | 34 | # Write fish items to a new file 35 | with open('./Fish.json', 'w') as file: 36 | json.dump(fish_items, file, indent=2) 37 | 38 | # Update the original Curiosities.json file without fish items 39 | with open('./Curiosities.json', 'w') as file: 40 | json.dump(non_fish_items, file, indent=2) 41 | 42 | print(f"Extracted {len(fish_items)} fish items to Fish.json") 43 | print(f"Updated Curiosities.json with {len(non_fish_items)} non-fish items") 44 | 45 | if __name__ == "__main__": 46 | extract_fish() 47 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Welcome to [No Man’s Sky Recipes](https://nomansskyrecipes.com/) 2 | 3 | ![image](https://user-images.githubusercontent.com/5970177/219064525-4f4709b1-a768-40c7-95dd-41a5d123e925.png) 4 | 5 | ## Project Structure 6 | 7 | Inside of the project, you'll see the following folders and files: 8 | 9 | ``` 10 | / 11 | ├── public/ 12 | │ └── 13 | ├── src/ 14 | │ ├── assets/ 15 | │ │ └── 16 | │ ├── components/ 17 | │ │ └── 18 | │ ├── data/ 19 | │ │ └── 20 | │ ├── layouts/ 21 | │ │ └── 22 | │ └── pages/ 23 | │ └── 24 | │ └── untils/ 25 | └── package.json 26 | ``` 27 | 28 | Astro looks for `.astro` or `.md` files in the `src/pages/` directory. Each page is exposed as a route based on its file name. 29 | 30 | There's nothing special about `src/components/`, but that's where we like to put any Astro/React/Vue/Svelte/Preact components. 31 | 32 | Any static assets, like images, can be placed in the `public/` directory. 33 | 34 | ## Commands 35 | 36 | All commands are run from the root of the project, from a terminal: 37 | 38 | | Command | Action | 39 | | :--------------------- | :------------------------------------------------- | 40 | | `npm install` | Installs dependencies | 41 | | `npm run dev` | Starts local dev server at `localhost:3000` | 42 | | `npm run build` | Build your production site to `./dist/` | 43 | | `npm run preview` | Preview your build locally, before deploying | 44 | | `npm run astro ...` | Run CLI commands like `astro add`, `astro preview` | 45 | | `npm run astro --help` | Get help using the Astro CLI | 46 | 47 | -------------------------------------------------------------------------------- /src/components/Footer.jsx: -------------------------------------------------------------------------------- 1 | import { SITE } from '../config'; 2 | 3 | const navigation = [ 4 | { name: 'Refining', href: '/refining' }, 5 | { name: 'Cooking', href: '/cooking' }, 6 | { name: 'Crafting', href: '/crafting-guide' }, 7 | { name: 'Calculator', href: '/calculator' }, 8 | { name: 'Feedback', href: '/feedback' }, 9 | ]; 10 | 11 | export default function Footer() { 12 | return ( 13 | 46 | ); 47 | } -------------------------------------------------------------------------------- /src/pages/all-items/[page].astro: -------------------------------------------------------------------------------- 1 | --- 2 | import Layout from '@layouts/Layout.astro'; 3 | import Card from '@components/Card.astro'; 4 | import Pagination from '@components/Pagination.astro'; 5 | import { getSlug, sort } from '@utils/lookup.js'; 6 | import products from '@data/Products.json'; 7 | import raw from '@data/RawMaterials.json'; 8 | import cooking from '@data/Cooking.json'; 9 | import curiosities from '@data/Curiosities.json'; 10 | import conTech from '@data/ConstructedTechnology.json'; 11 | import tech from '@data/Technology.json'; 12 | import buildings from '@data/Buildings.json'; 13 | import other from '@data/Others.json'; 14 | import trade from '@data/Trade.json'; 15 | 16 | export async function getStaticPaths({ paginate }) { 17 | return paginate( 18 | sort([ 19 | ...raw, 20 | ...products, 21 | ...cooking, 22 | ...curiosities, 23 | ...conTech, 24 | ...tech, 25 | ...buildings, 26 | ...other, 27 | ...trade, 28 | ]), 29 | { pageSize: 24 } 30 | ); 31 | } 32 | // All paginated data is passed on the "page" prop 33 | const { page } = Astro.props; 34 | --- 35 | 36 | 41 |

All Items

42 | 43 |
44 | { 45 | page.data.map((item, index) => ( 46 | 57 | )) 58 | } 59 |
60 | 61 | 62 |
63 | -------------------------------------------------------------------------------- /src/components/table/Cell.astro: -------------------------------------------------------------------------------- 1 | --- 2 | import { Image } from 'astro:assets' 3 | import { getSlug } from '@utils/lookup.js'; 4 | 5 | interface CellData { 6 | id: string; 7 | name: string; 8 | amount?: number; 9 | colour: string; 10 | image?: string; 11 | description?: string; 12 | value?: number; 13 | } 14 | 15 | export interface Props { 16 | cell: CellData | string | number; 17 | } 18 | 19 | const { cell } = Astro.props; 20 | --- 21 | 22 | 48 | 49 | 50 | {typeof cell === 'string' || typeof cell === 'number' ? ( 51 | cell 52 | ) : cell && 'id' in cell ? ( 53 | <> 54 | {cell.name} 55 | 56 |
57 | 58 | {cell.name} 59 | {cell.amount && x{cell.amount}} 60 | 61 | {cell.image && ( 62 | {cell.name} 69 | )} 70 |
71 |
72 | 73 | ) : null} 74 | -------------------------------------------------------------------------------- /src/components/NestedList.astro: -------------------------------------------------------------------------------- 1 | --- 2 | import { Image } from 'astro:assets' 3 | import Accordion from '@components/Accordion.astro'; 4 | import { getSlug, type Item } from '@utils/lookup.js'; 5 | 6 | interface Props { 7 | items: { 8 | RequiredItems?: Item[]; 9 | Quantity?: number; 10 | }; 11 | } 12 | 13 | const { items } = Astro.props; 14 | --- 15 | 16 | {items.RequiredItems?.map((item, index) => { 17 | const quantity = item.Quantity * (items.Quantity || 1); 18 | return item.RequiredItems?.length ? ( 19 | 20 | 40 |
41 | 42 |
43 |
44 | ) : ( 45 | 63 | ); 64 | })} -------------------------------------------------------------------------------- /src/pages/crafting-guide/index.astro: -------------------------------------------------------------------------------- 1 | --- 2 | // Importing required components and data 3 | import Layout from '@layouts/Layout.astro'; 4 | import Table from '@components/table/Table.astro'; 5 | import products from '@data/Products.json'; 6 | import { getById } from '@utils/lookup.js'; 7 | import type { Item, RequiredItem } from '@utils/lookup.js'; 8 | 9 | interface ItemDetails { 10 | id: string; 11 | name: string; 12 | description: string; 13 | value: number; 14 | amount?: number; 15 | image: string; 16 | colour: string; 17 | } 18 | 19 | const createItemDetails = (item: Item, quantity?: number): ItemDetails => ({ 20 | id: item.Id, 21 | name: item.Name, 22 | description: item.Description, 23 | value: item.BaseValueUnits, 24 | ...(quantity && { amount: quantity }), 25 | image: item.Icon, 26 | colour: item.Colour, 27 | }); 28 | 29 | const createArray = (item: Item): { input_1?: ItemDetails; input_2?: ItemDetails; input_3?: ItemDetails; output: ItemDetails; value: number; } | undefined => { 30 | if (item.RequiredItems.length === 0) return; 31 | 32 | const requiredItems = item.RequiredItems.map((element) => { 33 | const requiredItem = getById(element.Id); 34 | return requiredItem ? createItemDetails(requiredItem, element.Quantity) : undefined; 35 | }).filter(Boolean) as ItemDetails[]; 36 | 37 | return { 38 | ...Object.fromEntries(requiredItems.map((item, index) => [`input_${index + 1}`, item])), 39 | output: createItemDetails(item), 40 | value: item.BaseValueUnits, 41 | }; 42 | }; 43 | 44 | // Define the columns to be displayed in the table 45 | const columns = [ 46 | { title: 'Input 1', field: 'input_1' }, 47 | { title: 'Input 2', field: 'input_2' }, 48 | { title: 'Input 3', field: 'input_3' }, 49 | { title: 'Product', field: 'output' }, 50 | { title: 'Value', field: 'value' }, 51 | ]; 52 | 53 | // Map the data and create an array of filtered items 54 | const data = products.map(createArray).filter(Boolean); 55 | 56 | --- 57 | 58 | 63 | 72 | -------------------------------------------------------------------------------- /src/components/Card.astro: -------------------------------------------------------------------------------- 1 | --- 2 | import { Image } from 'astro:assets' 3 | 4 | import credit from '../assets/img/credits.png'; 5 | const { card, hide, index, loading } = Astro.props; 6 | --- 7 | 8 | 62 | 63 | { 64 | index != 0 && index % 6 == 0 ? ( 65 |
66 | 75 | 76 |
77 | ) : null 78 | } 79 | 80 | -------------------------------------------------------------------------------- /src/pages/refining/index.astro: -------------------------------------------------------------------------------- 1 | --- 2 | // Importing required components and data 3 | import Layout from '@layouts/Layout.astro'; 4 | import Table from '@components/table/Table.astro'; 5 | import refinery from '@data/Refinery.json'; 6 | import { getById } from '@utils/lookup.js'; 7 | import type { Item } from '@utils/lookup.js'; 8 | 9 | // Interfaces for defining the shape of input and output objects 10 | interface Input { 11 | Id: string; 12 | Quantity: number; 13 | } 14 | 15 | interface Output { 16 | Id: string; 17 | Quantity: number; 18 | } 19 | 20 | interface Refinery { 21 | Inputs: Input[]; 22 | Output: Output; 23 | } 24 | 25 | interface TableItem { 26 | input_1?: Item; 27 | input_2?: Item; 28 | input_3?: Item; 29 | output: Item; 30 | description: string; 31 | value: number; 32 | } 33 | 34 | // Improve type safety and readability 35 | const createArray = (item: Refinery): TableItem | undefined => { 36 | const inputs = item.Inputs.map((element) => createItemData(element)).filter(Boolean); 37 | const output = createItemData(item.Output); 38 | 39 | if (!output) return undefined; 40 | 41 | return { 42 | input_1: inputs[0], 43 | input_2: inputs[1], 44 | input_3: inputs[2], 45 | output, 46 | description: output.description, 47 | value: output.value, 48 | }; 49 | }; 50 | 51 | // Extract item data creation to a separate function 52 | const createItemData = (element: Input | Output): Item | undefined => { 53 | const item: Item | undefined = getById(element.Id); 54 | if (!item) return undefined; 55 | 56 | return { 57 | id: item.Id, 58 | name: item.Name, 59 | description: item.Description, 60 | value: item.BaseValueUnits, 61 | amount: element.Quantity, 62 | image: item.Icon, 63 | colour: item.Colour, 64 | }; 65 | }; 66 | 67 | // Define the columns to be displayed in the table 68 | const columns = [ 69 | { title: 'Input 1', field: 'input_1' }, 70 | { title: 'Input 2', field: 'input_2' }, 71 | { title: 'Input 3', field: 'input_3' }, 72 | { title: 'Output', field: 'output' }, 73 | ]; 74 | 75 | // Use type assertion for better type inference 76 | const data = refinery.map(createArray).filter((item): item is TableItem => item !== undefined); 77 | --- 78 | 79 | 84 |
92 | -------------------------------------------------------------------------------- /src/pages/cooking/index.astro: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | // Importing required components and data 4 | import Layout from '@layouts/Layout.astro'; 5 | import Table from '@components/table/Table.astro'; 6 | import processor from '@data/NutrientProcessor.json'; 7 | import { getById } from '@utils/lookup.js'; 8 | import type { Item } from '@utils/lookup.js'; 9 | 10 | // Interfaces for defining the shape of input and output objects 11 | interface Input { 12 | Id: string; 13 | Quantity: number; 14 | } 15 | 16 | interface Output { 17 | Id: string; 18 | Quantity: number; 19 | } 20 | 21 | interface Processor { 22 | Inputs: Input[]; 23 | Output: Output; 24 | } 25 | // Function to create an array of data for each item 26 | const createArray = (item: Processor) => { 27 | 28 | // Map the inputs and get the details of each input item using `getById` function 29 | const inputs = item.Inputs.map((element) => { 30 | const i: Item | undefined = getById(element.Id); 31 | // If item is not found, return undefined 32 | if (!i) return; 33 | // Return the item details 34 | return { 35 | id: i.Id, 36 | name: i.Name, 37 | description: i.Description, 38 | value: i.BaseValueUnits, 39 | amount: element.Quantity, 40 | image: i.Icon, 41 | colour: i.Colour, 42 | }; 43 | }); 44 | 45 | // Get the details of the output item using `getById` function 46 | const o: Item | undefined = getById(item.Output.Id); 47 | // If item is not found, return undefined 48 | if (!o) return; 49 | // Return the item details 50 | const output = { 51 | id: o.Id, 52 | name: o.Name, 53 | description: o.Description, 54 | value: o.BaseValueUnits, 55 | amount: item.Output.Quantity, 56 | image: o.Icon, 57 | colour: o.Colour, 58 | }; 59 | 60 | // Combine the inputs and output data in a new object 61 | const newItem = { 62 | input_1: inputs[0], 63 | input_2: inputs[1], 64 | input_3: inputs[2], 65 | output, 66 | description: output.description, 67 | value: output.value, 68 | }; 69 | return newItem; 70 | }; 71 | 72 | // Define the columns to be displayed in the table 73 | const columns = [ 74 | { title: 'Input 1', field: 'input_1' }, 75 | { title: 'Input 2', field: 'input_2' }, 76 | { title: 'Input 3', field: 'input_3' }, 77 | { title: 'Output', field: 'output' } 78 | 79 | ]; 80 | 81 | // Map the data and create an array of filtered items 82 | const data = processor.map(createArray).filter(Boolean); 83 | --- 84 | 85 | 90 |
91 | 92 | 93 | -------------------------------------------------------------------------------- /src/components/Accordion.astro: -------------------------------------------------------------------------------- 1 | --- 2 | const { open = false, id } = Astro.props; 3 | --- 4 | 5 |

6 | 20 |

21 |
27 | 28 |
29 |
30 | 31 | 69 | 70 | -------------------------------------------------------------------------------- /src/pages/index.astro: -------------------------------------------------------------------------------- 1 | --- 2 | import Layout from '../layouts/Layout.astro'; 3 | import Card from '../components/Card.astro'; 4 | 5 | const cards = [ 6 | { 7 | name: 'Refining', 8 | description: 9 | 'Refining is a process of combining various ingredients with the use of a refiner.', 10 | button: 'View Recipes', 11 | image: '/images/refiner.webp', 12 | link: '/refining', 13 | }, 14 | 15 | { 16 | name: 'Cooking', 17 | description: 18 | 'Cooking is a process of combining various ingredients with the use of a Nutrient Processor.', 19 | button: 'View Recipes', 20 | image: '/images/cooker.webp', 21 | link: '/cooking', 22 | }, 23 | { 24 | name: 'Crafting', 25 | description: 26 | 'The player can craft technology upgrades for themseleves using blueprints found throughout the universe.', 27 | button: 'View Recipes', 28 | image: '/images/crafting.webp', 29 | link: '/crafting-guide', 30 | }, 31 | { 32 | name: 'Calculator', 33 | description: 34 | 'A calculator for helping your farming efforts by calculating exactly what you need to craft any item.', 35 | button: 'View Recipes', 36 | image: '/images/calculator.webp', 37 | link: '/calculator/1', 38 | }, 39 | { 40 | name: 'Technology', 41 | description: 42 | "Technology is an item that upgrades a player's exosuit, multi-tool, exocraft, and starship. You learn how to install technologies from blueprints. ", 43 | button: 'View Recipes', 44 | image: 'https://app.nmsassistant.com/assets/images/constructedTechnology/57.png', 45 | link: '/technology/1', 46 | }, 47 | { 48 | name: 'Buildings', 49 | description: 50 | 'Base building allows the player to build multiple bases, which can be used for farming, storage and recharging Hazard Protection or Shield.', 51 | button: 'View Recipes', 52 | image: 'https://app.nmsassistant.com/assets/images/building/46.png', 53 | link: '/buildings/1', 54 | }, 55 | { 56 | name: 'Curiosities', 57 | description: 58 | 'Curiosities are items that can be found in the universe. They can be sold for units or used to craft other items.', 59 | button: 'View Recipes', 60 | image: 'https://app.nmsassistant.com/assets/images/curiosities/40.png', 61 | link: '/curiosities/1', 62 | }, 63 | { 64 | name: 'Raw Materials', 65 | description: "List of the raw materials in No Man's Sky", 66 | button: 'View Recipes', 67 | image: 'https://app.nmsassistant.com/assets/images/rawMaterials/1.png', 68 | link: '/raw/1', 69 | }, 70 | ]; 71 | --- 72 | 73 |
74 |

No Man's Sky Recipes

75 |

76 | Refiners | Crafting | Cooking 77 |

78 |
79 | 80 |
81 |
82 | {cards.map((card, index) => ( 83 | 84 | ))} 85 |
86 |
87 |
-------------------------------------------------------------------------------- /src/layouts/Layout.astro: -------------------------------------------------------------------------------- 1 | --- 2 | import '../assets/css/main.css'; 3 | import { SITE } from '@config'; 4 | import { inject } from '@vercel/analytics'; 5 | 6 | import Sidebar from '@layouts/Sidebar.jsx'; 7 | import Search from '@components/Search.astro'; 8 | import SearchModal from '@components/SearchModal.astro'; 9 | import Footer from '@components/Footer.jsx'; 10 | 11 | export interface Props { 12 | title?: string; 13 | author?: string; 14 | description?: string; 15 | ogImage?: string; 16 | slug?: string; 17 | } 18 | 19 | const { title = SITE.title, author = SITE.author, description = SITE.desc, slug } = Astro.props; 20 | 21 | const canonicalURL = new URL(Astro.url.pathname, Astro.site); 22 | 23 | inject(); 24 | --- 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | {title} 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 57 | 64 | 65 | 70 | 71 | 72 | 73 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 |
99 | 100 | -------------------------------------------------------------------------------- /src/pages/privacy.astro: -------------------------------------------------------------------------------- 1 | --- 2 | import Layout from '@layouts/Layout.astro'; 3 | --- 4 | 5 | 6 |
7 |

Privacy Policy

8 | 9 |
10 |
11 |

Analytics and Advertising

12 |

This website uses:

13 |
    14 |
  • Google Analytics - to understand website traffic and usage patterns
  • 15 |
  • Google AdSense - to display advertisements
  • 16 |
17 |

These services may use cookies and collect anonymous usage data. For more information about how these services handle your data, please refer to:

18 | 22 |
23 | 24 |
25 |

Cookies

26 |

This website uses cookies from Google Analytics and Google AdSense. You can control or delete cookies through your browser settings.

27 |
28 | 29 |
30 |

Your Privacy Choices

31 | 35 |
36 | 37 |
38 |

Changes to This Policy

39 |

We may update this privacy policy from time to time. We will notify you of any changes by posting the new policy on this page.

40 |

Last updated: {new Date().toLocaleDateString()}

41 |
42 | 43 |
44 |

Advertising

45 |

This site uses Google AdSense to display advertisements. These ads:

46 |
    47 |
  • May use cookies to personalize content and ads
  • 48 |
  • May collect and use data about your browsing activity
  • 49 |
  • Are provided by Google and its partners
  • 50 |
51 |

You can learn more about how Google uses data when you use our site by visiting Google's Privacy & Terms site.

52 |
53 | 54 |
55 |

This is a fan-made website. No Man's Sky™ and all related assets are trademarks 56 | of Hello Games. This site is not affiliated with or endorsed by Hello Games.

57 |
58 |
59 |
60 |
-------------------------------------------------------------------------------- /src/pages/privacy-policy.astro: -------------------------------------------------------------------------------- 1 | --- 2 | import Layout from '../layouts/Layout.astro'; 3 | import Form from '../components/Form.jsx'; 4 | --- 5 | 6 | 11 |

Privacy Policy

12 | 13 | Last updated: October 19, 2023 14 | 15 |

This Privacy Policy describes the policies and procedures of No Man's Sky Recipes ("we," "our," or "us") regarding the collection, use, and disclosure of information we receive from users of our website [nomansskyrecipes.com] (the "Site") and any associated services.

16 | 17 |

Information Collection and Use We do not collect or store any personal information from our users unless explicitly provided by the user through the contact form on our Site. The information we collect through the contact form may include the user's name, email address, and any additional message or inquiries they provide. We use this information solely for the purpose of responding to the user's inquiries and providing customer support.

18 | 19 |

Third-Party Services and Ads We may use third-party services, such as Google AdSense, to display advertisements on our Site. These third-party service providers may collect certain information, such as your IP address, to provide targeted ads based on your interests. These providers have their own privacy policies addressing how they collect, use, and disclose such information. We are not responsible for the privacy practices of these third parties.

20 | 21 |

Disclosure of Personal Information We do not sell, trade, or otherwise transfer personal information to third parties. However, we may disclose personal information in the following circumstances:

22 | 23 |

With the user's consent When required by law or to protect our rights In the event of a merger, acquisition, or sale of all or a portion of our assets Security We are committed to protecting the security of your personal information and take reasonable measures to prevent unauthorized access, disclosure, or alteration. However, please be aware that no method of transmission or storage over the Internet is completely secure, and therefore, we cannot guarantee its absolute security.

24 | 25 |

Links to Other Sites Our Site may contain links to other websites. Please note that we have no control over the content, privacy policies, or practices of these external sites. We strongly advise you to review the privacy policy of any third-party sites you visit.

26 | 27 |

Children's Privacy Our Site is not directed to children under the age of 13, and we do not knowingly collect personal information from children. If we discover that we have collected personal information from a child under 13, we will promptly delete it from our records.

28 | 29 |

GDPR Compliance If you are located in the European Economic Area (EEA), you have certain rights under the General Data Protection Regulation (GDPR) regarding the personal information we collect and process. These rights include:

30 | 31 |

The right to access, update, or delete your personal information The right to restrict or object to the processing of your personal information The right to data portability The right to withdraw consent at any time, where applicable To exercise any of these rights, please contact us using the information provided at the end of this Privacy Policy.

32 | 33 |

Changes to This Privacy Policy This Privacy Policy is effective as of October 19, 2023 and will remain in effect except with respect to any changes in its provisions in the future, which will be in effect immediately after being posted on this page.

34 | 35 |

Contact Us If you have any questions about this Privacy Policy or would like to exercise your rights under GDPR, please contact us at https://nomansskyrecipes.com/feedback.

36 |
37 | -------------------------------------------------------------------------------- /src/assets/css/main.css: -------------------------------------------------------------------------------- 1 | @font-face { 2 | font-family: 'FuturaProBook'; 3 | src: url('/fonts/FuturaProBook.woff2') format('woff2'), 4 | url('/fonts/FuturaProBook.woff') format('woff'); 5 | font-weight: normal; 6 | font-style: normal; 7 | font-display: block; 8 | } 9 | 10 | @tailwind base; 11 | @tailwind components; 12 | @tailwind utilities; 13 | 14 | #table { 15 | @apply border-0 16 | } 17 | 18 | #table .tabulator-row .tabulator-cell { 19 | @apply p-0 border-b border-r border-gray-500 transition-all hover:opacity-80 min-w-[275px] inline-flex items-center text-white 20 | } 21 | 22 | #table .tabulator-row .tabulator-cell[tabulator-field="value"] { 23 | @apply text-base px-3 24 | } 25 | 26 | #table .tabulator-row .tabulator-cell picture { 27 | @apply min-w-[50px] 28 | } 29 | 30 | #table .tabulator-row .tabulator-cell:last-of-type { 31 | @apply border-r-0 32 | } 33 | 34 | #table .tabulator-cell > a { 35 | @apply w-full h-full block 36 | } 37 | 38 | #table .tabulator-cell > a > div { 39 | @apply flex flex-row-reverse items-center justify-end h-full text-white text-base gap-2 px-2 40 | } 41 | 42 | :is( 43 | [style="background: #FFC356"], 44 | [style="background: #DEDCD1"], 45 | [style="background: #F3A923"], 46 | [style="background: #DE921F"], 47 | [style="background: #8A7F72"], 48 | [style="background: #6AD01E"], 49 | [style="background: #FFAD00"], 50 | [style="background: #CCCCCC"] 51 | ) { 52 | @apply !text-black 53 | } 54 | 55 | #table .tabulator-cell > a > div[style="background: #CCCCCC"] { 56 | @apply !bg-slate-900 !text-white 57 | } 58 | 59 | #table .tabulator-row { 60 | @apply bg-gray-800 61 | } 62 | 63 | #table .tabulator-row.tabulator-row-even { 64 | @apply bg-gray-800 65 | } 66 | 67 | #table .tabulator-header .tabulator-col { 68 | @apply bg-black text-base text-white p-2 min-w-[275px] !important 69 | } 70 | 71 | #table .tabulator-header .tabulator-col:last-of-type { 72 | @apply border-r-0 73 | } 74 | 75 | #table .tabulator-arrow { 76 | @apply border-b-blue-500 77 | } 78 | 79 | #table .tabulator-col.tabulator-sortable[aria-sort="descending"] .tabulator-arrow { 80 | @apply border-t-blue-500 81 | } 82 | 83 | #table .tabulator-footer { 84 | @apply bg-black text-base text-white py-2 px-10 border-0 overflow-x-scroll 85 | } 86 | 87 | #table .tabulator-page { 88 | @apply inline-flex items-center transition-colors rounded border-0 bg-blue-500 px-2.5 py-1.5 text-xs font-medium text-black shadow-sm hover:bg-blue-800 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2 89 | } 90 | 91 | #table .tabulator-page.active { 92 | @apply bg-blue-700 hover:bg-blue-800 93 | } 94 | 95 | #table .tabulator-page-size { 96 | @apply rounded-md border-gray-300 py-[4.5px] pl-3 pr-10 text-xs focus:border-blue-500 focus:outline-none focus:ring-blue-500 sm:text-sm bg-blue-500 border-0 text-black 97 | } 98 | 99 | #table .tabulator-paginator { 100 | @apply text-white ml-5 101 | } 102 | 103 | .tabulator-tooltip.tabulator-popup-container { 104 | @apply text-base p-4 bg-black border-blue-500 rounded-md 105 | } 106 | 107 | .nms-bg { 108 | background-size: cover; 109 | background-position: center; 110 | position: relative; 111 | isolation: isolate; 112 | min-height: 100vh; 113 | } 114 | .nms-bg::after { 115 | content: ""; 116 | left: 0; 117 | height: 100%; 118 | width: 100%; 119 | background: #051413s; 120 | position: absolute; 121 | top: 0; 122 | opacity: 0.7; 123 | z-index: -1; 124 | } 125 | 126 | 127 | .btn { 128 | @apply inline-flex items-center rounded-md border border-transparent bg-blue-500 px-3 py-2 text-sm font-medium leading-4 text-black shadow-sm hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2 129 | } 130 | 131 | #results li a { 132 | @apply select-none px-4 py-2 block hover:bg-blue-500 hover:text-black focus:bg-blue-500 focus:text-black 133 | } 134 | 135 | .disclaimer { 136 | font-size: 0.8rem; 137 | color: #fff; 138 | text-align: center; 139 | padding: 1rem; 140 | line-height: 1.2 141 | } 142 | -------------------------------------------------------------------------------- /src/components/table/Table.astro: -------------------------------------------------------------------------------- 1 | --- 2 | import '../../assets/css/tabulator.css'; 3 | import TableHead from '@components/table/Head.astro'; 4 | import TableCell from '@components/table/Cell.astro'; 5 | import { Image } from 'astro:assets'; 6 | 7 | interface Column { 8 | title: string; 9 | field: string; 10 | } 11 | 12 | interface TableRow { 13 | input_1: object; 14 | input_2: object; 15 | input_3: object; 16 | output: object; 17 | description?: string; 18 | value?: number; 19 | } 20 | 21 | export interface Props { 22 | title: string; 23 | image: string; 24 | image_width: number; 25 | image_height: number; 26 | columns: Column[]; 27 | sort?: string; 28 | data: TableRow[]; 29 | } 30 | 31 | const { title, image, image_width, image_height, columns, sort = 'output', data } = Astro.props; 32 | --- 33 | 34 | 45 | 46 |
47 |
51 |
52 | 60 |

{title}

61 |
62 | 63 |
64 |
65 |

Layout:

66 | 74 | 82 |
83 |
84 | 85 |
86 | 100 |
101 |
102 |
103 | 104 | 105 | {data.map((row) => ( 106 | 107 | {columns.map((column) => ( 108 | 109 | ))} 110 | 111 | ))} 112 | 113 |
114 | 115 | 116 | 160 | -------------------------------------------------------------------------------- /src/utils/lookup.ts: -------------------------------------------------------------------------------- 1 | // Importing data files 2 | import raw from '../data/RawMaterials.json'; 3 | import products from '../data/Products.json'; 4 | import cooking from '../data/Cooking.json'; 5 | import curiosities from '../data/Curiosities.json'; 6 | import fish from '../data/Fish.json'; 7 | import conTech from '../data/ConstructedTechnology.json'; 8 | import tech from '../data/Technology.json'; 9 | import tMod from '../data/TechnologyModule.json'; 10 | import other from '../data/Others.json'; 11 | import refiner from '../data/Refinery.json'; 12 | import nut from '../data/NutrientProcessor.json'; 13 | import build from '../data/Buildings.json'; 14 | import trade from '../data/Trade.json'; 15 | 16 | export type RequiredItem = { 17 | Id: string; 18 | Quantity: number; 19 | }; 20 | 21 | // Defining the interface for an Item 22 | type Item = { 23 | Id: string; 24 | fishId?: string; 25 | Name: string; 26 | Description: string; 27 | Group: string; 28 | Icon: string; 29 | Colour: string; 30 | BaseValueUnits: number; 31 | RequiredItems?: Item[]; 32 | Quantity?: number; 33 | Output?: { 34 | Id: string; 35 | Quantity: number; 36 | }; 37 | Value?: string; 38 | }; 39 | 40 | // Mapping the prefixes of item id to the actual data sources 41 | const dataSources = { 42 | raw, 43 | prod: products, 44 | cook: cooking, 45 | cur: [...curiosities, ...fish], 46 | conTech, 47 | tech, 48 | tMod, 49 | other, 50 | ref: refiner, 51 | nut: nut, 52 | build, 53 | trade, 54 | }; 55 | 56 | // Mapping the prefixes of item id to the corresponding slugs 57 | const slugs = { 58 | raw: '/raw/', 59 | prod: '/products/', 60 | cook: '/cooking/', 61 | cur: '/curiosities/', 62 | fish: '/fish/', 63 | conTech: '/technology/', 64 | tech: '/technology/', 65 | tMod: '/technology/', 66 | other: '/other/', 67 | ref: '/refinery/', 68 | nut: '/nutrient-processor/', 69 | build: '/buildings/', 70 | trade: '/other/', 71 | }; 72 | 73 | const labels = { 74 | raw: 'Raw Materials', 75 | prod: 'Products', 76 | cook: 'Cooking', 77 | cur: 'Curiosities', 78 | fish: 'Fish', 79 | conTech: 'Technology', 80 | tech: 'Technology', 81 | tMod: 'Technology', 82 | other: 'Other', 83 | ref: 'Refinery', 84 | nut: 'Nutrient Processor', 85 | build: 'Buildings', 86 | trade: 'Other', 87 | }; 88 | 89 | const getSlug = (id: string): string => { 90 | // Extract the prefix of the item id by splitting the id by its numeric part 91 | const prefix = id.split(/\d/)[0]; 92 | 93 | // Special handling for 'cur' prefix 94 | if (prefix === 'cur') { 95 | const item = getById(id); 96 | if (item && 'fishId' in item) { 97 | return slugs['fish']; 98 | } 99 | } 100 | 101 | // Return the slug corresponding to the prefix or "item" if prefix not found 102 | return slugs[prefix] || 'item'; 103 | }; 104 | 105 | // Returns the label corresponding to the item id 106 | const getLabel = (id: string): string => { 107 | // Extract the prefix of the item id by splitting the id by its numeric part 108 | const prefix = id.split(/\d/)[0]; 109 | // Return the slug corresponding to the prefix or "item" if prefix not found 110 | return labels[prefix] || 'item'; 111 | }; 112 | 113 | // Returns the item corresponding to the id from a given data source 114 | const findById = (source: Item[], id: string): Item => { 115 | // Find the item from the data source with a matching id 116 | return source.find((p) => p.Id === id); 117 | }; 118 | 119 | const findOutput = (id: string): Item[] => { 120 | return Object.values(dataSources).flatMap(source => 121 | source.filter(item => item.Output?.Id === id) 122 | ); 123 | }; 124 | 125 | const findInput = (id: string): Item[] => { 126 | return Object.values(dataSources).flatMap(source => 127 | source.filter(item => item.Inputs?.some(input => input.Id === id)) 128 | ); 129 | }; 130 | 131 | // Returns the item corresponding to the id from the appropriate data source 132 | const getById = (id: string): Item | undefined => { 133 | // Extract the prefix of the item id by splitting the id by its numeric part 134 | const prefix = id.split(/\d/)[0]; 135 | // Get the data source corresponding to the prefix 136 | const source = dataSources[prefix]; 137 | 138 | // If source not found, log an error and return undefined 139 | if (!source) { 140 | console.error(`No data source found for prefix: ${id} : ${prefix}`); 141 | return undefined; 142 | } 143 | // Find the item from the source 144 | const item = source.find((item) => item.Id === id); 145 | // If item not found, log a warning and return undefined 146 | if (!item) { 147 | console.warn(`Item not found: ${id}`); 148 | return undefined; 149 | } 150 | // Return the found item 151 | return item; 152 | }; 153 | 154 | const getLength = (list) => { 155 | let length = dataSources[list].filter((item) => !item.RequiredItems || item.RequiredItems.length != 0).length; 156 | return length; 157 | }; 158 | 159 | const sort = (data) => { 160 | const sortData = data.sort((a, b) => { 161 | const nameA = a?.Name?.toUpperCase() ?? ''; 162 | const nameB = b?.Name?.toUpperCase() ?? ''; 163 | return nameA.localeCompare(nameB); 164 | }); 165 | return sortData; 166 | }; 167 | 168 | const sortTable = (data) => { 169 | return data.sort((a, b) => { 170 | const nameA = a?.output?.name?.toUpperCase() ?? ''; 171 | const nameB = b?.output?.name?.toUpperCase() ?? ''; 172 | return nameA.localeCompare(nameB); 173 | }); 174 | }; 175 | 176 | // Add findInput to the export statement 177 | export { getSlug, getLabel, getById, findOutput, findInput, getLength, sort, sortTable }; 178 | export type { Item }; 179 | 180 | // <(.*?)> - Match any character between < and >, and capture it -------------------------------------------------------------------------------- /src/components/Form.jsx: -------------------------------------------------------------------------------- 1 | export default function Form() { 2 | return ( 3 |
4 | {/* Contact information */} 5 |
6 | {/* Decorative angle backgrounds */} 7 | 37 | 70 | 103 |

Share your feedback

104 |

105 | Let us know if you have any ideas or suggestions on how to improve our site. 106 |

107 |
108 | 109 | {/* Contact form */} 110 |
111 |

Send us a message

112 | 117 |
118 | 121 |
122 | 129 |
130 |
131 |
132 | 135 |
136 | 143 |
144 |
145 |
146 | 149 |
150 | 156 |
157 |
158 |
159 | 162 |
163 |