No description
  • JavaScript 69.6%
  • CSS 17.8%
  • HTML 12.6%
Find a file
2025-11-25 13:57:38 -08:00
node_modules stuff 2025-11-22 12:45:45 -08:00
public changes 2025-11-25 13:57:38 -08:00
readme analyzer updates 2025-11-19 19:40:08 -08:00
uploads first commit 2025-11-13 14:35:52 -08:00
.env Themes Control 2025-11-18 13:23:43 -08:00
env.example Themes Control 2025-11-18 13:23:43 -08:00
gitignore Themes Control 2025-11-18 13:23:43 -08:00
package-lock.json stuff 2025-11-22 12:45:45 -08:00
package.json stuff 2025-11-22 12:45:45 -08:00
README.md r2 storage 2025-11-18 01:28:24 -08:00
server.js changes 2025-11-24 23:20:42 -08:00

Innovative Axis

A secure, read-only Node.js markdown reader with session-based protection and Cloudflare R2 storage.

Features

  • 🔒 Session-Based Security: Content only accessible through website UI
  • ☁️ R2 Cloud Storage: Documents stored in Cloudflare R2
  • 🎨 Professional Themes: 5 beautiful themes (Dark, Light, Ocean, Forest, Sunset)
  • 📱 Responsive Layout: Resizable containers with flexible positioning
  • 🔍 Smart Search & Filters: Search content and filter by tags
  • 📥 Clean Downloads: Download markdown without metadata
  • 🛡️ Security Hardened: Helmet, rate limiting, input sanitization

Prerequisites

  • Node.js (v18 or higher)
  • npm
  • Cloudflare R2 account and bucket

Installation

  1. Clone and install dependencies:
npm install
  1. Add ReadexPro font files to public/fonts/:

    • ReadexPro-Light.ttf
    • ReadexPro-Regular.ttf
    • ReadexPro-Medium.ttf
    • ReadexPro-SemiBold.ttf
  2. Configure environment variables:

cp .env.example .env
  1. Edit .env with your R2 credentials:
# Server Configuration
PORT=3000
NODE_ENV=development

# Session Security (REQUIRED - CHANGE IN PRODUCTION!)
SESSION_SECRET=your-secure-random-string-here

# Cloudflare R2 Configuration
R2_ACCOUNT_ID=your-account-id
R2_ACCESS_KEY_ID=your-access-key
R2_SECRET_ACCESS_KEY=your-secret-key
R2_BUCKET_NAME=your-bucket-name

# R2 Jurisdiction (optional: default, eu, fedramp)
R2_JURISDICTION=default

R2 Bucket Structure

Your R2 bucket should be organized as follows:

your-bucket/
├── documents/
│   ├── doc1.md
│   ├── doc2.md
│   └── doc3.md
└── assets/
    ├── doc1/
    │   ├── image1.png
    │   └── image2.jpg
    └── doc2/
        └── diagram.svg

Markdown File Format

Each markdown file must include metadata at the top:

<!-- META
ID: unique-document-id
Tag: Category
Title: Document Title
Description: Brief description shown in feed
-->

# Your Content Here

Regular markdown content with support for:
- Images: `![alt](assets/doc-id/image.png)`
- Code blocks
- Tables
- And all standard markdown features

Metadata Fields:

  • ID: Unique identifier (used in URLs and asset paths)
  • Tag: Category/tag for filtering
  • Title: Document title (shown in feed and downloads)
  • Description: Brief description (shown in feed)

Running the Application

Development mode (with auto-reload):

npm run dev

Production mode:

npm start

The application will be available at http://localhost:3000

Security Features

🔐 Session-Based Protection

How it works:

  1. User visits homepage → Server creates session cookie
  2. User browses documents → All API calls require valid session
  3. Direct API access (bots, scrapers) → Rejected with "Please visit website" message

What's protected:

  • GET /api/files - Document list
  • GET /api/file/:id - Document content
  • GET /api/download/:id - Document downloads
  • GET /assets/:id/:filename - Asset files

What's public:

  • Homepage (creates session)
  • Static files (CSS, JS, fonts)
  • Health check endpoint

🛡️ Additional Security

  • Helmet: Security headers (CSP, XSS protection)
  • Rate Limiting: 100 requests per 15 minutes per IP
  • Input Sanitization: Path traversal prevention
  • HTTPS Enforcement: Automatic redirect in production
  • Session Security: HTTPOnly, SameSite cookies
  • Size Limits: Request body limited to 1MB

Usage

For Visitors

  1. Open the application in your browser
  2. Select a document from the feed panel
  3. Read content with beautiful markdown rendering
  4. Download documents using the "Download .md" button
  5. Switch themes and adjust layout as desired

Theme Switching

Click the hamburger menu (☰) and select from:

  • Dark (default)
  • Light
  • Ocean
  • Forest
  • Sunset

Layout Adjustment

  • Resize: Drag the space between containers
  • Swap: Click the swap button (⇄) in reader header

Search & Filter

  • Search: Click search icon, type to filter documents
  • Filter: Click filter icon, select a tag to filter by category

API Endpoints

All endpoints require a valid session cookie (created by visiting the homepage).

GET /api/files

Returns list of all documents with metadata.

Response:

[
  {
    "id": "unique-doc-id",
    "tag": "Tutorial",
    "title": "Getting Started",
    "description": "Learn the basics"
  }
]

GET /api/file/:id

Returns document content without metadata.

Response:

{
  "content": "# Document Content\n\nMarkdown here...",
  "id": "unique-doc-id"
}

GET /api/download/:id

Downloads document as .md file (uses title from metadata for filename).

GET /assets/:id/:filename

Proxies asset files from R2 (images, PDFs, etc.).

GET /api/health

Health check endpoint (no session required).

Response:

{
  "status": "healthy",
  "timestamp": "2024-01-01T00:00:00.000Z",
  "environment": "production"
}

Project Structure

innovative-axis/
├── public/
│   ├── fonts/              # ReadexPro font files
│   ├── css/
│   │   └── styles.css      # All styling
│   ├── js/
│   │   └── app.js          # Frontend JavaScript
│   └── index.html          # Main HTML
├── server.js               # Express server with R2 integration
├── package.json
├── .env.example            # Environment variables template
├── .env                    # Your configuration (not in git)
├── .gitignore
└── README.md

Uploading Documents

This app is read-only. Use a separate application to upload documents to your R2 bucket.

Your upload app should:

  1. Validate markdown has proper metadata
  2. Upload to documents/ folder in R2
  3. Upload assets to assets/{doc-id}/ folder
  4. Use appropriate permissions (write access to R2)

Production Deployment

Pre-deployment Checklist

  • Change SESSION_SECRET to a secure random string
  • Set NODE_ENV=production
  • Configure R2 credentials
  • Set up HTTPS/SSL certificate
  • Configure reverse proxy (nginx/Cloudflare)
  • Review rate limits and adjust if needed

Environment Variables

All required variables must be set:

  • SESSION_SECRET - CRITICAL: Must be changed from default
  • R2_ACCOUNT_ID - Your Cloudflare account ID
  • R2_ACCESS_KEY_ID - R2 API token access key
  • R2_SECRET_ACCESS_KEY - R2 API token secret
  • R2_BUCKET_NAME - Your R2 bucket name

Deployment Platforms

Cloudflare Workers:

  • Set environment variables in Workers dashboard
  • Deploy with Wrangler CLI

Other Platforms (Heroku, Railway, DigitalOcean):

  • Set environment variables in platform dashboard
  • Ensure Node.js v18+ runtime

Technologies Used

  • Backend: Node.js, Express
  • Storage: Cloudflare R2 (S3-compatible)
  • Security: Helmet, express-rate-limit, express-session
  • Markdown: Marked.js
  • Frontend: Vanilla JavaScript, HTML5, CSS3
  • Font: ReadexPro family

Security Best Practices

  1. Always use HTTPS in production
  2. Never commit .env file to git
  3. Use strong SESSION_SECRET (32+ random characters)
  4. Keep dependencies updated (npm audit fix)
  5. Monitor rate limit violations
  6. Use read-only R2 credentials for this app
  7. Regular security audits

Troubleshooting

"Missing required environment variables" error

Check that all R2 variables are set in .env file.

Session not persisting

Ensure cookies are enabled in browser. Check that SESSION_SECRET is set.

Documents not loading

  1. Verify R2 credentials are correct
  2. Check bucket name and document paths
  3. Ensure documents have proper metadata format
  4. Check R2 access permissions

Assets not displaying

Verify asset paths match folder structure in R2 and document metadata ID.

License

MIT