A premium Developer Portfolio, Repository Catalog, and Markdown Documentation Explorer built with Laravel. Features automated GitHub sync, a developer blog platform, and secure user access with 2FA.
An open-source platform to showcase GitHub repositories, publish developer blogs, and boost discoverability through SEO-optimized project pages, sitemaps, and llms.txt — built for developers who want their work indexed, linked, and shared.
About
Developer Hub is an open-source platform for developer visibility. It syncs GitHub repositories into rich, crawlable documentation pages and gives registered users a dashboard to submit blogs, link external repos, and share suggestions — all moderated through an admin approval workflow.
Whether you are publishing SDK docs, listing community projects, or growing organic traffic to your GitHub profile, Developer Hub handles the SEO layer so your repositories and writing get found.
Features
GitHub repo sync — Automatically pulls repositories, READMEs, file trees, and metadata from a GitHub profile via github:sync
SEO-first project pages — Structured project pages with code explorer, schema markup, sitemap.xml, and llms.txt for search engines and AI crawlers
Community blogs — Users can register, write Markdown posts, and publish after admin approval
Linked repositories — Submit and showcase external GitHub repos alongside official projects
User dashboard — Manage profile, blogs, linked repos, and API tokens
Admin command center — Approve submissions, manage users, and configure site settings
Authentication — Email verification, password reset, social login (OAuth), and two-factor authentication
REST API — Sanctum-powered API for linked repo integrations
Requirements
PHP 8.3+
Composer 2
Node.js 18+ and npm
SQLite (default) or MySQL / PostgreSQL
Installation
# Clone the repository
git clone https://github.com/ghostcompiler/ghostcompiler.git
cd ghostcompiler
# Install dependencies and set up the app
composer setup
Copy .env.example to .env and configure at minimum:
Variable
Description
APP_NAME
Application name (e.g. Developer Hub)
APP_URL
Public URL of your deployment
DB_CONNECTION
Database driver (sqlite by default)
GITHUB_TOKEN
GitHub personal access token for repo sync
Sync GitHub repositories
php artisan github:sync
Development server
composer dev
This starts the Laravel server, queue worker, log tail, and Vite dev server concurrently.
Project structure
Path
Purpose
app/Http/Controllers/
Web and API controllers
app/Console/Commands/
github:sync, project tree caching
app/Models/
Projects, blogs, linked repos, users
resources/views/
Blade templates for public and dashboard UI
routes/web.php
Public routes, auth, dashboard, SEO endpoints
routes/api.php
Sanctum API routes
SEO endpoints
URL
Description
/sitemap.xml
Dynamic sitemap for projects, blogs, and repo files
/llms.txt
Machine-readable site summary for AI crawlers
/robots.txt
Crawler directives with sitemap reference
Testing
composer test
License
This project is open-sourced under the MIT license.
Development Environment
Built using ServBay
Mac M4 Tested
macOS Apple Silicon
Powered by ServBay
Filesmain
Repository Files
Loading file structure...
Select a file from the repository tree to inspect its code.
config/session.php
<?php
use Illuminate\Support\Str;
return [
/*
|--------------------------------------------------------------------------
| Default Session Driver
|--------------------------------------------------------------------------
|
| This option determines the default session driver that is utilized for
| incoming requests. Laravel supports a variety of storage options to
| persist session data. Database storage is a great default choice.
|
| Supported: "file", "cookie", "database", "memcached",
| "redis", "dynamodb", "array"
|
*/
'driver' => env('SESSION_DRIVER', 'database'),
/*
|--------------------------------------------------------------------------
| Session Lifetime
|--------------------------------------------------------------------------
|
| Here you may specify the number of minutes that you wish the session
| to be allowed to remain idle before it expires. If you want them
| to expire immediately when the browser is closed then you may
| indicate that via the expire_on_close configuration option.
|
*/
'lifetime' => (int) env('SESSION_LIFETIME', 120),
'expire_on_close' => env('SESSION_EXPIRE_ON_CLOSE', false),
/*
|--------------------------------------------------------------------------
| Session Encryption
|--------------------------------------------------------------------------
|
| This option allows you to easily specify that all of your session data
| should be encrypted before it's stored. All encryption is performed
| automatically by Laravel and you may use the session like normal.
|
*/
'encrypt' => env('SESSION_ENCRYPT', false),
/*
|--------------------------------------------------------------------------
| Session File Location
|--------------------------------------------------------------------------
|
| When utilizing the "file" session driver, the session files are placed
| on disk. The default storage location is defined here; however, you
| are free to provide another location where they should be stored.
|
*/
'files' => storage_path('framework/sessions'),
/*
|--------------------------------------------------------------------------
| Session Database Connection
|--------------------------------------------------------------------------
|
| When using the "database" or "redis" session drivers, you may specify a
| connection that should be used to manage these sessions. This should
| correspond to a connection in your database configuration options.
|
*/
'connection' => env('SESSION_CONNECTION'),
/*
|--------------------------------------------------------------------------
| Session Database Table
|--------------------------------------------------------------------------
|
| When using the "database" session driver, you may specify the table to
| be used to store sessions. Of course, a sensible default is defined
| for you; however, you're welcome to change this to another table.
|
*/
'table' => env('SESSION_TABLE', 'sessions'),
/*
|--------------------------------------------------------------------------
| Session Cache Store
|--------------------------------------------------------------------------
|
| When using one of the framework's cache driven session backends, you may
| define the cache store which should be used to store the session data
| between requests. This must match one of your defined cache stores.
|
| Affects: "dynamodb", "memcached", "redis"
|
*/
'store' => env('SESSION_STORE'),
/*
|--------------------------------------------------------------------------
| Session Sweeping Lottery
|--------------------------------------------------------------------------
|
| Some session drivers must manually sweep their storage location to get
| rid of old sessions from storage. Here are the chances that it will
| happen on a given request. By default, the odds are 2 out of 100.
|
*/
'lottery' => [2, 100],
/*
|--------------------------------------------------------------------------
| Session Cookie Name
|--------------------------------------------------------------------------
|
| Here you may change the name of the session cookie that is created by
| the framework. Typically, you should not need to change this value
| since doing so does not grant a meaningful security improvement.
|
*/
'cookie' => env(
'SESSION_COOKIE',
Str::slug((string) env('APP_NAME', 'laravel')).'-session'
),
/*
|--------------------------------------------------------------------------
| Session Cookie Path
|--------------------------------------------------------------------------
|
| The session cookie path determines the path for which the cookie will
| be regarded as available. Typically, this will be the root path of
| your application, but you're free to change this when necessary.
|
*/
'path' => env('SESSION_PATH', '/'),
/*
|--------------------------------------------------------------------------
| Session Cookie Domain
|--------------------------------------------------------------------------
|
| This value determines the domain and subdomains the session cookie is
| available to. By default, the cookie will be available to the root
| domain without subdomains. Typically, this shouldn't be changed.
|
*/
'domain' => env('SESSION_DOMAIN'),
/*
|--------------------------------------------------------------------------
| HTTPS Only Cookies
|--------------------------------------------------------------------------
|
| By setting this option to true, session cookies will only be sent back
| to the server if the browser has a HTTPS connection. This will keep
| the cookie from being sent to you when it can't be done securely.
|
*/
'secure' => env('SESSION_SECURE_COOKIE'),
/*
|--------------------------------------------------------------------------
| HTTP Access Only
|--------------------------------------------------------------------------
|
| Setting this value to true will prevent JavaScript from accessing the
| value of the cookie and the cookie will only be accessible through
| the HTTP protocol. It's unlikely you should disable this option.
|
*/
'http_only' => env('SESSION_HTTP_ONLY', true),
/*
|--------------------------------------------------------------------------
| Same-Site Cookies
|--------------------------------------------------------------------------
|
| This option determines how your cookies behave when cross-site requests
| take place, and can be used to mitigate CSRF attacks. By default, we
| will set this value to "lax" to permit secure cross-site requests.
|
| See: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie#samesitesamesite-value
|
| Supported: "lax", "strict", "none", null
|
*/
'same_site' => env('SESSION_SAME_SITE', 'lax'),
/*
|--------------------------------------------------------------------------
| Partitioned Cookies
|--------------------------------------------------------------------------
|
| Setting this value to true will tie the cookie to the top-level site for
| a cross-site context. Partitioned cookies are accepted by the browser
| when flagged "secure" and the Same-Site attribute is set to "none".
|
*/
'partitioned' => env('SESSION_PARTITIONED_COOKIE', false),
/*
|--------------------------------------------------------------------------
| Session Serialization
|--------------------------------------------------------------------------
|
| This value controls the serialization strategy for session data, which
| is JSON by default. Setting this to "php" allows the storage of PHP
| objects in the session but can make an application vulnerable to
| "gadget chain" serialization attacks if the APP_KEY is leaked.
|
| Supported: "json", "php"
|
*/
'serialization' => 'json',
];