{"id":45343093,"url":"https://github.com/neanrie/yourls.frontend-links","last_synced_at":"2026-03-06T11:00:53.913Z","repository":{"id":338201514,"uuid":"1156071381","full_name":"neanrie/yourls.frontend-links","owner":"neanrie","description":"Link-in-bio page plugin for YOURLS — manage sections, links, profile and custom icons from the admin panel.","archived":false,"fork":false,"pushed_at":"2026-02-25T22:01:48.000Z","size":1662,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-03-02T22:35:07.016Z","etag":null,"topics":["link-in-bio","linktree-alternative","yourls","yourls-plugin"],"latest_commit_sha":null,"homepage":"","language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/neanrie.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-02-12T08:21:02.000Z","updated_at":"2026-03-02T18:15:21.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/neanrie/yourls.frontend-links","commit_stats":null,"previous_names":["nyerou/yourls.frontend-links","neanrie/yourls.frontend-links"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/neanrie/yourls.frontend-links","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/neanrie%2Fyourls.frontend-links","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/neanrie%2Fyourls.frontend-links/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/neanrie%2Fyourls.frontend-links/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/neanrie%2Fyourls.frontend-links/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/neanrie","download_url":"https://codeload.github.com/neanrie/yourls.frontend-links/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/neanrie%2Fyourls.frontend-links/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30173340,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-06T07:56:45.623Z","status":"ssl_error","status_checked_at":"2026-03-06T07:55:55.621Z","response_time":250,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["link-in-bio","linktree-alternative","yourls","yourls-plugin"],"created_at":"2026-02-21T11:00:17.396Z","updated_at":"2026-03-06T11:00:53.900Z","avatar_url":"https://github.com/neanrie.png","language":"PHP","funding_links":[],"categories":["Plugins"],"sub_categories":["F"],"readme":"# Frontend Links [![Listed in Awesome YOURLS!](https://img.shields.io/badge/Awesome-YOURLS%20Plugin-C5A3BE)](https://github.com/YOURLS/awesome-yourls/)\n\nLink-in-bio page plugin for YOURLS — manage sections, links, profile and custom icons from the admin panel.\n\n## Features\n\n- **Sections \u0026 Links** management with drag-friendly sort order\n- **Profile** customization (name, bio, avatar with upload/restore)\n- **Custom icons** (SVG code or image upload) alongside built-in Font Awesome icons\n- **Theme system**: switchable themes from the admin; each theme has its own templates and assets\n- **Default theme**: minimal responsive design with automatic light/dark mode (system preference)\n- **Social previews**: redirect page fetches `og:image`, `og:type`, `og:description`, `theme-color` and `\u003ctitle\u003e` from the target URL for accurate social link previews (Discord, Slack, Twitter, Facebook)\n- **Branded redirect page**: interstitial with target page metadata before redirecting (can be disabled)\n- **Branded 404 page**: custom error page matching your site design (can be disabled)\n- **Auto mode**: generates `index.php`, `.htaccess` and `robots.txt` at the document root, no manual setup needed\n- **robots.txt generation**: auto-generated in auto mode — lists all YOURLS short URLs with destination comments, configurable `Allow`/`Disallow` per install, timestamped, auto-updates on link changes\n- **Redirect rules**: optional HTTP→HTTPS and www canonical redirects injected into the generated `.htaccess`; direction auto-detected from `YOURLS_SITE`; both combined into a single 301 when active together\n- **Manual mode**: include `fl_render_page()` from any PHP file\n- **Subdirectory support**: works when YOURLS is installed in a subdirectory (e.g. `example.com/yourls`)\n  - Short URLs resolve at the root (`/keyword` not `/yourls/keyword`)\n  - Stats links (`keyword+`) are corrected to include the subdirectory\n  - Auto-generated `.htaccess` handles URL rewriting\n  - JSON-LD and meta tags use the root domain\n- **Click tracking**: short URL clicks are correctly counted in YOURLS stats; clicks from the link-in-bio page are identified as `?ref=fl-homepage` in Traffic Sources\n- **CSP compliant**: no inline scripts or styles, compatible with YOURLS 1.10+ strict Content Security Policy\n- **Security**: SVG sanitization (XSS prevention), SSRF protection on URL fetching, uploads directory lockdown\n- **i18n ready** with French translation included\n\n## Demos (Screens or GIFs)\n\n\u003cdetails\u003e\n\u003csummary\u003eSections \u0026 Links management\u003c/summary\u003e\n\u003cimg src=\"docs/screens/links-sections-demo-add_edit_delete.gif\" width=\"600\" alt=\"Sections and links CRUD\"\u003e\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003eProfile \u0026 Avatar\u003c/summary\u003e\n\u003cimg src=\"docs/screens/profile-avatars-demo.gif\" width=\"600\" alt=\"Profile and avatar management\"\u003e\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003eCustom icons\u003c/summary\u003e\n\u003cimg src=\"docs/screens/add-icons-demo.png\" width=\"600\" alt=\"Adding custom icons\"\u003e\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003eSettings \u0026 Feature toggles\u003c/summary\u003e\n\u003cimg src=\"docs/screens/settings-infos-demo.png\" width=\"600\" alt=\"Options panel and feature toggles\"\u003e\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003eSocial preview (Discord)\u003c/summary\u003e\n\u003cimg src=\"docs/screens/meta-seo-demo-discord.png\" width=\"400\" alt=\"Discord embed with OG metadata\"\u003e\n\u003c/details\u003e\n\n## Requirements\n\n- [YOURLS](https://yourls.org/) 1.9+\n- PHP 8.0+\n- PHP extensions: `fileinfo` (avatar \u0026 icon uploads), `curl` (OG metadata fetching)\n- Apache with `mod_rewrite` (for auto mode)\n\n## Installation\n\n1. Download or clone this repository into `user/plugins/frontend-links/`\n2. Activate the plugin in the YOURLS admin (`Manage Plugins`)\n3. Go to the **Frontend Administration** admin page to install tables and configure\n\n## Configuration\n\n### Display mode\n\n| Mode          | Description                                                                                                                             |\n| ------------- | --------------------------------------------------------------------------------------------------------------------------------------- |\n| **Automatic** | The plugin creates `index.php` and `.htaccess` at the document root. The link page is served at `/` and short URLs resolve at the root. |\n| **Manual**    | Include the rendering function in your own PHP file.                                                                                    |\n\nManual mode example:\n\n```php\n\u003c?php\nrequire_once __DIR__ . '/yourls/includes/load-yourls.php';\nfl_render_page();\n```\n\n### Themes\n\nThemes live in `themes/\u003cslug\u003e/` and contain a `theme.json` manifest, a `templates/` folder (`home.php`, `redirect.php`, `404.php`) and an `assets/` folder. The active theme is selected from **Options → Theme** in the admin panel.\n\nThe `default` theme (minimal, responsive, system light/dark mode) is active out of the box. Additional themes can be added by dropping a folder in `themes/`.\n\nSee **[docs/theming.md](docs/theming.md)** for a full guide on creating your own theme.\n\n### robots.txt\n\nIn auto mode the plugin generates a `robots.txt` at the document root. The file lists every YOURLS short URL and is automatically re-written whenever a short URL is created, edited or deleted (file is only touched when content actually changes).\n\nThe **Short URLs indexing** option (admin → Options → robots.txt) controls the directive used for each short URL:\n\n| Value | Directive | Effect |\n|---|---|---|\n| **Disallow** *(default)* | `Disallow: /keyword` | Google skips the redirect page and indexes the destination directly — saves crawl budget |\n| **Allow** | `Allow: /keyword` | Googlebot crawls the branded redirect page before following to the destination |\n\n### Redirections\n\nOptional redirect rules injected into the generated `.htaccess` (auto mode, Apache with `mod_rewrite` only). Applied immediately when saved.\n\n| Option | Description |\n|---|---|\n| **HTTP → HTTPS** | Forces all `http://` requests to `https://` (301). Skip if your server or CDN already handles this. |\n| **WWW canonical** | Redirects the alternate www variant to the canonical domain. Direction is auto-detected from `YOURLS_SITE`: a non-www site redirects `www.example.com → example.com`, a www site redirects `example.com → www.example.com`. The redirect target always uses the scheme from `YOURLS_SITE`. When combined with HTTPS, both are resolved in a single 301. |\n\n### Features\n\n| Option                    | Description                                                                                                                                                                                               |\n| ------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| **Branded redirect page** | When enabled (default), short URL clicks show a branded interstitial with metadata fetched from the target page (title, image, description, theme color). When disabled, uses a direct HTTP 302 redirect. |\n| **Branded 404 page**      | When enabled (default), unknown URLs show a branded error page. When disabled, returns a basic HTTP 404.                                                                                                  |\n\n### Short links\n\nWhen a link is entered without a protocol (e.g. `git`), the YOURLS domain is added automatically:\n\n- `git` → `https://example.com/git`\n\nAn option allows including the YOURLS subdirectory in generated URLs if needed.\n\n### Profile\n\n- **Name** and **Bio** displayed on the page\n- **Avatar**: upload an image or use an external URL. Previous avatar can be restored.\n- **SEO Title** and **Description** for meta tags\n\n### Custom icons\n\n- **SVG code**: paste inline SVG, use `stroke=\"currentColor\"` for theme adaptation (automatically sanitized)\n- **Image**: upload JPG, PNG, GIF, WebP, or SVG (max 1 MB)\n\n## File structure\n\n```\nfrontend-links/\n├── plugin.php              # Plugin entry point, hooks and filters\n├── ajax.php                # AJAX endpoint for admin CRUD\n├── migrate.php             # One-time interactive migration (fl_* options → frontend_settings)\n├── includes/\n│   ├── functions.php       # Core logic (CRUD, URL helpers, file management)\n│   ├── icons.php           # Font Awesome + custom icon system\n│   ├── install.php         # Database table creation\n│   ├── render.php          # Homepage rendering logic\n│   └── themes.php          # Theme resolution and discovery\n├── templates/\n│   └── admin.php           # Admin panel interface (not themed)\n├── assets/                 # Shared assets (not themed)\n│   ├── css/\n│   │   ├── admin.css       # Admin panel styles\n│   │   └── all.min.css     # Font Awesome (vendor)\n│   └── js/\n│       ├── admin.js        # Admin panel logic (CSP-compliant)\n│       ├── redirect.js     # Redirect delay script\n│       └── stats-rewrite.js # Stats link subdirectory fix\n├── themes/\n│   ├── default/            # Minimal light/dark theme (active by default)\n│   │   ├── theme.json\n│   │   ├── templates/\n│   │   │   ├── home.php\n│   │   │   ├── redirect.php\n│   │   │   └── 404.php\n│   │   └── assets/css/\n│   │       ├── home.css\n│   │       └── pages.css\n│   └── \u003cyour-theme\u003e/       # Additional themes follow the same structure\n├── uploads/                # Avatars \u0026 custom icon images (gitignored)\n│   └── icons/\n└── languages/              # Translation files (.pot, .po)\n```\n\n## Security\n\n- **SVG sanitization**: all SVG input (code and file uploads) is stripped of `\u003cscript\u003e` tags, event handlers, `javascript:` URLs, `\u003cforeignObject\u003e` and external `\u003cuse\u003e` references\n- **SSRF protection**: target URL metadata fetching only allows `http`/`https` schemes and blocks private/reserved IP ranges\n- **Uploads lockdown**: `.htaccess` auto-generated at activation — blocks PHP execution, adds `Content-Security-Policy` and `X-Content-Type-Options: nosniff` for SVG files, with the correct `RewriteBase` for root and subdirectory installs\n- **CSRF protection**: all AJAX requests verified with YOURLS nonces\n- **Authentication**: admin panel and AJAX endpoint require YOURLS authentication\n- **Prepared statements**: all database queries use parameterized queries (PDO)\n\n## Changelog\n\nSee [CHANGELOG.md](docs/changelog.md) for the full version history.\n\n## License\n\nMIT\n\n## Author\n\n[Neanrie](https://github.com/neanrie)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fneanrie%2Fyourls.frontend-links","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fneanrie%2Fyourls.frontend-links","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fneanrie%2Fyourls.frontend-links/lists"}