nyxcore-systems
6 min read

Unleashing Your Stories: NyxBook Now Imports from GitHub & Zip, Plus a Sleek New Look!

We've just supercharged NyxBook's content ingestion, letting you import your narrative projects directly from GitHub repositories and `.zip` archives. Plus, a fresh, intuitive sidebar redesign makes navigating your stories smoother and more delightful than ever.

nyxBookGitHubZipUploadImportUI/UXFrontendBackendTypeScriptNext.jsWebDevelopmentProductivity

At NyxBook, our mission is to empower creators to build, organize, and explore their fictional worlds with unparalleled ease. Today, we're thrilled to announce a significant leap forward in making that process even smoother: you can now effortlessly bring your existing narrative projects into NyxBook directly from GitHub repositories and .zip files!

This isn't just about adding new buttons; it's about breaking down barriers and integrating NyxBook more deeply into your existing creative workflows. Alongside these powerful new import capabilities, we've also given our main application sidebar a beautiful, cohesive redesign, enhancing your overall navigation experience.

Let's dive into what's new!

Seamless Content Ingestion: GitHub & Zip Imports

We know many of you manage your story drafts, character sheets, and world-building notes in various formats, often version-controlled on GitHub or neatly packaged in .zip files. Our goal was to make migrating these rich resources into NyxBook as simple as possible.

From GitHub to NyxBook: A Coder's Dream

For those who treat their stories like code, GitHub is home. Now, NyxBook can connect directly to your public (and eventually private, via your BYOK token) GitHub repositories.

Here's how we made it happen:

  1. Smart Repo Scanning: A new service, src/server/services/nyxbook-github.ts, acts as a digital librarian. Its checkGitHubForBook() function intelligently scans your selected repository for a common book/ directory structure, giving you immediate feedback on whether a valid project is found.
  2. API-Powered Fetching: Once a book/ directory is identified, importFromGitHub() springs into action. It leverages the GitHub API to fetch your content, ensuring you get the latest version of your story.
  3. Intelligent Parsing & Database Integration: The fetched content is then processed by our robust, shared parsing functions (more on these in a moment). Characters, beats, chapters, and personas are all extracted and seamlessly integrated into your NyxBook database, ready for your creative touch.
  4. Security First: To protect against malicious input, we've implemented strict regex validation for GitHub owner and repo names, ensuring only valid and safe patterns are processed.
typescript
// Example from src/server/trpc/routers/nyxbook.ts
// Robust regex validation for GitHub owner and repo
owner: z.string().regex(/^[a-zA-Z0-9]([a-zA-Z0-9-]*[a-zA-Z0-9])?$/, { message: "Invalid GitHub owner format" }).max(39),
repo: z.string().regex(/^[a-zA-Z0-9._-]+$/, { message: "Invalid GitHub repo format" }).max(100),

Zip It Up: Local Projects Made Easy

For those who prefer local archiving or have private projects not on GitHub, .zip file uploads are now a core import method.

Our new REST POST endpoint at src/app/api/v1/nyxbook/import/route.ts handles the magic:

  1. Multipart Form Data: We accept multipart/form-data for secure and efficient file transfers.
  2. JSZip Extraction: On the server, we use JSZip to carefully extract your archive's contents.
  3. Auto-Detecting Book Roots: The findBookRoot() function intelligently scans the extracted files to automatically detect the main book/ directory (or similar common structures), simplifying the import process for you.
  4. Safety & Limits: We've built in robust protections, including path traversal prevention, a 20MB file size limit, a 200-entry limit for zip contents, and a strict .md-only filter, ensuring only relevant and safe files are processed.
  5. Clean Up: All temporary directories created during the extraction are meticulously cleaned up afterward.

Shared Smarts: Consistent Parsing

Whether you're importing from GitHub or a .zip file, your content goes through the same battle-tested parsing pipeline. We've consolidated and exported key parser functions like parseCharacters, parseBeats, splitDualLayer, and countWords from src/server/services/nyxbook-import.ts. This ensures consistency and reliability across all import methods, guaranteeing your characters, plot beats, and chapters are always interpreted correctly. We also sanitized metadata to prevent leaking any filesystem paths.

A Brand New Import Experience

All these powerful backend features are brought to life with a fully redesigned import interface on src/app/(dashboard)/dashboard/nyxbook/page.tsx. We've fused all import methods (GitHub, Zip, and the existing Server Path option) into collapsible groups within the page sidebar. You'll find:

  • A searchable repository combobox with type-to-filter functionality for GitHub imports.
  • Instant book/ directory scanning feedback as you select a repo.
  • An intuitive drag-and-drop zone for .zip file uploads.

This redesign makes discovering and using the import features a truly delightful experience.

The Sidebar Aesthetic: A Fresh New Look

Beyond the import capabilities, we've given the main application sidebar (src/components/layout/sidebar.tsx) a significant aesthetic upgrade. Our goal was to match the beloved InPageSidebar style, creating a more cohesive, modern, and intuitive navigation experience across the entire application.

You'll notice refined details like:

  • Compact & Clean: text-xs for menu items, rounded links for a softer look.
  • Clear Active States: bg-nyx-accent/10 for active links provides subtle yet clear feedback.
  • Subtle Grouping: text-[9px] group labels with /60 opacity enhance organization without clutter.
  • Spacious & Balanced: Optimized gap-2 spacing between items, w-12/w-48 widths for collapsed/expanded states, and h-3.5 icons for perfect alignment.

These changes collectively enhance readability, improve visual hierarchy, and contribute to a more premium feel, making your journey through NyxBook more enjoyable.

Lessons from the Trenches: Our Development Challenges

No significant feature rollout comes without its quirks and learning moments. Here's one challenge we navigated:

TypeScript's Set Iteration Gotcha

During the development of the .zip route's findBookRoot() function, I encountered a peculiar TypeScript error (TS2802) when trying to iterate directly over a Set<string> using a for...of loop.

typescript
// This failed with TS2802 without --downlevelIteration
// for (const dir of dirs) { ... }

This error indicates that Set can only be iterated with the --downlevelIteration compiler option enabled in tsconfig.json. Since our project's tsconfig doesn't use this option (and for good reason, to avoid unnecessary polyfills or larger bundle sizes for modern JS environments), a direct for...of was out.

The Workaround: The immediate fix was to convert the Set to an array using Array.from() before iteration:

typescript
// The successful workaround
for (const dir of Array.from(dirs)) {
  // ... our logic here
}

This is a known TypeScript gotcha that often catches developers off guard, and it's even documented in our internal CLAUDE.md for project-specific quirks! It's a great reminder to always be aware of your tsconfig's implications on language features.

Addressing Existing Technical Debt

During code review, an important security concern was flagged regarding the pre-existing server-path import procedure. It currently accepts any filesystem path, posing a path traversal risk. While this particular issue wasn't part of this session's scope, it's now a high-priority item on our radar. We're actively considering restricting it to a secure upload directory (/tmp/nyxcore-uploads/) or removing it entirely now that GitHub and zip uploads cover most use cases. Security is paramount, and addressing technical debt like this is crucial for long-term project health.

What's Next?

With these exciting features implemented, type-checked, lint-cleaned, and code review fixes applied, we're ready for deployment! Our immediate next steps include:

  1. Thorough End-to-End Testing: Rigorous testing of both GitHub and zip imports to ensure everything works flawlessly.