Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 19 additions & 7 deletions app/docs/[[...slug]]/page.tsx → app/[[...slug]]/page.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
import type { Metadata } from 'next';
import { DocsLayout } from 'fumadocs-ui/layouts/docs';
import { DocsPage, DocsBody } from 'fumadocs-ui/page';
import { notFound } from 'next/navigation';
import { source } from '@/lib/source';
import { generatePageMetadata, getCanonicalUrl } from '@/lib/seo-utils';
import { CustomNavbar } from '@/lib/components/CustomNavbar';
import { getFinalPageTitle } from '@/lib/h1-extractor';
import { readFile } from 'fs/promises';
import { getMDXComponents } from '@/mdx-components';
import { baseOptions } from '../layout.config';

export default async function Page({
params,
Expand All @@ -23,12 +24,23 @@ export default async function Page({
const MDX = page.data.body;

return (
<DocsPage toc={page.data.toc} full={page.data.full}>
<CustomNavbar />
<DocsBody>
<MDX components={getMDXComponents()} />
</DocsBody>
</DocsPage>
<DocsLayout
{...baseOptions}
tree={source.pageTree}
nav={{
title: 'DeployStack Docs',
url: '/',
}}
sidebar={{
defaultOpenLevel: 1
}}
>
<DocsPage toc={page.data.toc} full={page.data.full}>
<DocsBody>
<MDX components={getMDXComponents()} />
</DocsBody>
</DocsPage>
</DocsLayout>
);
}

Expand Down
22 changes: 0 additions & 22 deletions app/docs/layout.tsx

This file was deleted.

30 changes: 0 additions & 30 deletions app/docs/sitemap.xml/route.ts

This file was deleted.

4 changes: 2 additions & 2 deletions app/layout.config.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import type { BaseLayoutProps } from 'fumadocs-ui/layouts/shared';

export const baseOptions: BaseLayoutProps = {
// Navigation bar configuration (now handled by CustomNavbar)
// Navigation bar configuration
nav: {
title: 'DeployStack Docs',
url: '/docs',
url: '/',
},

// GitHub repository for edit links
Expand Down
39 changes: 28 additions & 11 deletions check-links.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,19 +25,35 @@ const extractLinks = (content) => {

// Check if a local file exists
const checkLocalFile = (linkPath, filePath) => {
if (linkPath.startsWith('/docs/')) {
// Check for internal links (starting with / but not external URLs)
if (linkPath.startsWith('/') && !linkPath.startsWith('//') && !linkPath.startsWith('http')) {
// Remove hash fragment before checking file existence
const [baseUrl] = linkPath.split('#');
const localPath = path.join(process.cwd(), baseUrl);

try {
fs.accessSync(localPath, fs.constants.F_OK);
console.log(` ✅ ${linkPath}`);
return true;
} catch (err) {
console.log(` ❌ ${linkPath} → File not found`);
return false;
// Map the URL to the actual file location
// Since our URLs are now root-level but files are in docs/
const actualFilePath = path.join(process.cwd(), 'docs', baseUrl.substring(1));

// Try both .mdx and .md extensions
const possiblePaths = [
actualFilePath + '.mdx',
actualFilePath + '.md',
path.join(actualFilePath, 'index.mdx'),
path.join(actualFilePath, 'index.md')
];

for (const possiblePath of possiblePaths) {
try {
fs.accessSync(possiblePath, fs.constants.F_OK);
console.log(` ✅ ${linkPath}`);
return true;
} catch (err) {
// Continue to next possible path
}
}

console.log(` ❌ ${linkPath} → File not found (checked: ${possiblePaths.map(p => path.relative(process.cwd(), p)).join(', ')})`);
return false;
}
return null; // not a local file
};
Expand Down Expand Up @@ -79,7 +95,8 @@ const processFile = async (filePath) => {

let allValid = true;
for (const link of links) {
if (link.url.startsWith('/docs/')) {
if (link.url.startsWith('/') && !link.url.startsWith('//') && !link.url.startsWith('http')) {
// Internal link (root-level)
const isValid = checkLocalFile(link.url, filePath);
if (!isValid) allValid = false;
} else if (link.url.startsWith('http')) {
Expand Down Expand Up @@ -109,7 +126,7 @@ const processDirectory = async (dir) => {
if (stat.isDirectory()) {
const isValid = await processDirectory(filePath);
if (!isValid) allValid = false;
} else if (file.endsWith('.md')) {
} else if (file.endsWith('.md') || file.endsWith('.mdx')) {
const isValid = await processFile(filePath);
if (!isValid) allValid = false;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
---
title: Application Logo Configuration
description: DeployStack logo configuration guide. Add a custom logo to your application with automatic WebP conversion, CDN delivery, and square format optimization.
---

# Application Logo Configuration

Add a custom logo to make your application stand out in the DeployStack catalog. Your logo will be automatically optimized and served through our CDN for the best performance.

## Adding Your Logo

Configure your logo in `.deploystack/config.yml` - [DeployStack Configuration File Reference](/docs/deploystack/deploystack-config-file):

```yaml
application:
logo: "https://example.com/path/to/logo.png"
```

## Logo Requirements

### Supported Formats

- PNG (`.png`)
- JPEG (`.jpg`, `.jpeg`)
- WebP (`.webp`)
- SVG (`.svg`)

### Size Guidelines

- Maximum input: 2 MB.
- Final output will be:
- Square format (1:1 aspect ratio)
- Maximum 500x500 pixels
- Input images will be:
- Resized if larger than 500px in either dimension
- Centered and cropped to maintain 1:1 aspect ratio
- Padded with transparency if needed to achieve square format

## Image Processing

When you configure a logo, DeployStack automatically:

1. Downloads your original image
2. Optimizes it for web delivery
3. Converts it to WebP format
4. Stores it on our CDN
5. Serves it through our global CDN network

### Optimization Process

- Images larger than 500px in either dimension are resized
- Conversion to WebP for optimal compression
- Automatic quality optimization for web delivery

## Notes

- The logo configuration is optional
- You can update your logo at any time by modifying the config file
- Logo changes are processed only when made on the default branch
- Previous logo versions are automatically cleaned up
Loading