diff --git a/pica-lufi/Dockerfile b/pica-lufi/Dockerfile
new file mode 100644
index 0000000000000000000000000000000000000000..6d917fdfe6d1b5403a4687d1a5fc90a9a781f998
--- /dev/null
+++ b/pica-lufi/Dockerfile
@@ -0,0 +1,19 @@
+FROM debian:buster
+
+ARG LUFI_BUILD_VERSION=0.04.6
+
+RUN apt-get update \
+&& apt-get -yq install build-essential libssl-dev libio-socket-ssl-perl liblwp-protocol-https-perl libpq-dev wget unzip \
+&& apt-get clean && cpan Carton \
+&& wget https://github.com/ldidry/lufi/archive/${LUFI_BUILD_VERSION}.zip && unzip ${LUFI_BUILD_VERSION}.zip \
+&& rm ${LUFI_BUILD_VERSION}.zip && mv lufi-${LUFI_BUILD_VERSION} lufi
+
+COPY lufi.conf /lufi/lufi.conf
+
+WORKDIR /lufi
+
+RUN carton install --deployment --without=test --without=sqlite --without=mysql
+
+CMD ["carton", "exec", "hypnotoad", "-f", "/lufi/script/lufi"]
+
+COPY picadrop /lufi/themes/picadrop
diff --git a/pica-lufi/docker-compose.yml b/pica-lufi/docker-compose.yml
new file mode 100644
index 0000000000000000000000000000000000000000..15ffdf44fdabbc7c487c706c6bd44160de35612f
--- /dev/null
+++ b/pica-lufi/docker-compose.yml
@@ -0,0 +1,35 @@
+version: "3.7"
+
+volumes:
+  lufidb-data:
+  lufi-data:
+  lufi-files:
+
+services:
+  lufidb:
+    image: postgres:12
+    container_name: lufidb
+    restart: always
+    env_file:
+      - lufi.env
+    volumes:
+      - lufidb-data:/var/lib/postgresql/data
+
+  lufi:
+    image: lufi
+    container_name: lufi
+    init: true
+    depends_on:
+      - lufidb
+    ports:
+      - 8081:8081
+    links:
+      - lufidb:lufidb
+    volumes:
+      - lufi-data:/lufi/data
+      - lufi-files:/lufi/files
+    labels:
+      - "traefik.frontend.rule=Host:drop.test.picasoft.net"
+      - "traefik.backend=lufi"
+      - "traefik.port=8081"
+      - "traefik.enable=true"
diff --git a/pica-lufi/lufi.conf b/pica-lufi/lufi.conf
new file mode 100644
index 0000000000000000000000000000000000000000..fd8ed0b930b2ee0022b8506a740ac91e929d4a45
--- /dev/null
+++ b/pica-lufi/lufi.conf
@@ -0,0 +1,334 @@
+# vim:set sw=4 ts=4 sts=4 ft=perl expandtab:
+{
+    ####################
+    # Hypnotoad settings
+    ####################
+    # see http://mojolicio.us/perldoc/Mojo/Server/Hypnotoad for a full list of settings
+    hypnotoad => {
+        # array of IP addresses and ports you want to listen to
+        # you can specify a unix socket too, like 'http+unix://%2Ftmp%2Flufi.sock'
+        listen => ['http://0.0.0.0:8081'],
+        # if you use Lufi behind a reverse proxy like Nginx, you want to set proxy to 1
+        # if you use Lufi directly, let it commented
+        proxy  => 1,
+
+        # Please read http://mojolicious.org/perldoc/Mojo/Server/Hypnotoad#workers
+        # to adjust this to your server
+        workers => 30,
+        clients => 1,
+    },
+
+    # Put a way to contact you here and uncomment it
+    # You can put some HTML in it
+    # MANDATORY
+    contact       => '<a href="mailto:picasoft@assos.utc.fr">Contact</a>',
+
+    # Put an URL or an email address to receive file reports and uncomment it
+    # It's for make reporting illegal files easy for users
+    # MANDATORY
+    report => 'picasoft@assos.utc.fr',
+
+    # Array of random strings used to encrypt cookies
+    # optional, default is ['fdjsofjoihrei'], PLEASE, CHANGE IT
+    secrets        => ['gizjvnkzahmpob'],
+
+    # Name of the instance, displayed next to the logo
+    # optional, default is Lufi
+    instance_name => 'PicaDrop',
+
+    # Choose a theme. See the available themes in `themes` directory
+    # Optional, default is 'default'
+    theme         => 'picadrop',
+
+    # Length of the random URL
+    # optional, default is 8
+    length            => 8,
+
+    # How many URLs will be provisioned in a batch ?
+    # optional, default is 5
+    provis_step       => 5,
+
+    # Max number of URLs to be provisioned
+    # optional, default is 100
+    provisioning      => 100,
+
+    # Length of the modify/delete token
+    # optional, default is 32
+    token_length      => 32,
+
+    # Max file size, in octets
+    # You can write it 100*1024*1024
+    # optional, no default
+    max_file_size     => 104857600,
+
+    # If you want to have piwik statistics, provide a piwik image tracker
+    # Only the image tracker is allowed, no javascript
+    # optional, no default
+    #piwik_img         => 'https://piwik.example.org/piwik.php?idsite=1&amp;rec=1',
+
+    # Broadcast_message which will displayed on the index page
+    # optional, no default
+    #broadcast_message => 'Maintenance',
+
+    # Default time limit for files
+    # Valid values are 0, 1, 7, 30 and 365
+    # optional, default is 0 (no limit)
+    default_delay     => 0,
+
+    # Number of days after which the files will be deleted, even if they were uploaded with "no delay" (or value superior to max_delay)
+    # A warning message will be displayed on homepage
+    # optional, default is 0 (no limit)
+    max_delay         => 15,
+
+    # Size thresholds: if you want to define max delays for different sizes of file
+    # The keys are size in Bytes, you can't have 10*1000*10000 as key
+    # If a file is smaller than the smallest configured size, it will have a expiration delay of max_delay (see above)
+    # optional, default is using max_delay (see above) for all sizes
+    #delay_for_size  => {
+    #    10000000   => 90, # between 10MB and 50MB => max is 90 days, less than 10MB => max is max_delay (see above)
+    #    50000000   => 60, # between 50MB ans 1GB  => max is 60 days
+    #    1000000000 => 2,  # more than 1GB         => max is 2 days
+    #},
+
+    # URL sub-directory in which you want Lufi to be accessible
+    # example: you want to have Lufi under https://example.org/lufi/
+    # => set prefix to '/lufi' or to '/lufi/', it doesn't matter
+    # optional, defaut is /
+    prefix        => '/',
+
+    # Array of authorized domains for API calls.
+    # If you want to authorize everyone to use the API: ['*']
+    # optional, no domains allowed by default
+    #allowed_domains   => ['http://1.example.com', 'http://2.example.com'],
+
+    # Define a path to the upload directory, where the uploaded files will be stored
+    # You can define it relative to lufi directory or set an absolute path
+    # Remember that it has to be in a directory writable by Lufi user
+    # DO NOT CHANGE THIS IF FILES HAVE BEEN ALREADY UPLOADED: THEY WILL NOT BE DOWNLOADABLE ANYMORE
+    # optional, default is 'files'
+    #upload_dir           => 'files',
+
+    # Allow to add a password on files, asked before allowing to download files
+    # optional, default is 0
+    allow_pwd_on_files => 1,
+
+    # Force all files to be in "Burn after reading mode"
+    # optional, default is 0
+    #force_burn_after_reading => 0,
+
+    # If set, the files' URLs will always use this domain
+    # optional, no default
+    #fixed_domain => 'example.org',
+
+    # Abuse reasons
+    # Set an integer in the abuse field of a file in the database and it will not be downloadable anymore
+    # The reason will be displayed to the downloader, according to the reasons you will configure here.
+    # optional, no default
+    abuse => {
+       0 => 'Copyright infringment',
+       1 => 'Illegal content',
+    },
+
+    ###############
+    # Mail settings
+    ###############
+
+    # Mail configuration
+    # See https://metacpan.org/pod/Mojolicious::Plugin::Mail#EXAMPLES
+    # optional, default to sendmail method with no arguments
+    mail => {
+        # Valid values are 'sendmail' and 'smtp'
+        how => 'smtp',
+        howargs => ['smtp.example.org']
+    },
+
+    # Email sender address
+    # optional, default to no-reply@lufi.io
+    mail_sender => 'picasoft@assos.utc.fr',
+
+    #############
+    # DB settings
+    #############
+
+    # Choose what database you want to use
+    # Valid choices are sqlite, postgresql and mysql (all lowercase)
+    # optional, default is sqlite
+    dbtype => 'postgresql',
+
+    # SQLite ONLY - only used if dbtype is set to sqlite
+    # Define a path to the SQLite database
+    # You can define it relative to lufi directory or set an absolute path
+    # Remember that it has to be in a directory writable by Lufi user
+    # optional, default is lufi.db
+    #db_path           => 'lufi.db',
+
+    # PostgreSQL ONLY - only used if dbtype is set to postgresql
+    # These are the credentials to access the PostgreSQL database
+    # mandatory if you choosed postgresql as dbtype
+    pgdb => {
+        database => 'lufidb',
+        host     => 'lufidb',
+        # optional, default is 5432
+        port     => 5432,
+        user     => 'lufidb',
+        pwd      => 'passwd',
+        # https://mojolicious.org/perldoc/Mojo/Pg#max_connections
+        # optional, default is 1
+        #max_connections => 1,
+    },
+
+    # MySQL ONLY - only used if dbtype is set to mysql
+    # These are the credentials to access the MySQL database
+    # mandatory if you choosed mysql as dbtype
+    #mysqldb => {
+    #    database => 'lufi',
+    #    host     => 'localhost',
+    #    # optional, default is 3306
+    #    #port     => 3306,
+    #    user     => 'DBUSER',
+    #    pwd      => 'DBPASSWORD',
+    #    # https://metacpan.org/pod/Mojo::mysql#max_connections
+    #    # optional, default is 5 (set to 0 to disable persistent connections)
+    #    #max_connections => 5,
+    #},
+
+    #############################################
+    # LDAP settings (authentication and features)
+    #############################################
+
+    # Set `ldap` if you want that only authenticated users can upload files
+    # Please note that everybody can still download files
+    # optional, no default
+    #ldap => {
+    #    uri         => 'ldaps://ldap.example.org',                 # server URI
+    #    user_tree   => 'ou=users,dc=example,dc=org',               # search base DN
+    #    bind_dn     => 'uid=ldap_user,ou=users,dc=example,dc=org', # search bind DN
+    #    bind_pwd    => 'secr3t',                                   # search bind password
+    #    user_attr   => 'uid',                                      # user attribute (uid, mail, sAMAccountName, etc.)
+    #    user_filter => '(!(uid=ldap_user))',                       # user filter (to exclude some users, etc.)
+    #    # optional start_tls configuration. See https://metacpan.org/pod/distribution/perl-ldap/lib/Net/LDAP.pod#start_tls
+    #    # don't set or uncomment if you don't want to configure it
+    #    start_tls => {
+    #       verify     => 'optional',
+    #       clientcert => '/etc/ssl/certs/ca-bundle.pem'
+    #    }
+    #},
+
+    # If you've set ldap above, the session will last `session_duration` seconds before
+    # the user needs to reauthenticate
+    # optional, default is 3600
+    #session_duration => 3600,
+
+    # If you use `ldap` for authentication, you can map some attributes from LDAP to be able to access them in Lufi
+    # Those attributes will be accessible with:
+    #   $c->current_user->{lufi_attribute_name} in Lufi backend files (all that is in `lib` directory)
+    #   <%= $self->current_user->{lufi_attribute_name} %> in templates files (in `themes` directory)
+    #
+    # Define the attributes like this: `lufi_attribute_name => 'LDAP_attribute_name'`
+    # Note that you can’t use `username` as a Lufi attribute name: this name is reserved and will contain the login of the user
+    # optional, no default
+    #ldap_map_attr => {
+    #    displayname => 'cn',
+    #    mail        => 'mail'
+    #},
+
+    # When using LDAP authentication, LDAP users can invite people (by mail) to use Lufi to send them files without
+    # being authenticated.
+    # This is where you configure the behavior of the invitations.
+    # You may need to fetch some attributes from LDAP to use some invitations settings. See `ldap_map_attr` above.
+    # optional, no default
+    #invitations => {
+    #   # The name of the key set in `ldap_map_attr` (above) that corresponds to the mail of the LDAP user
+    #   # optional, default is `mail`
+    #   mail_attr => 'mail',
+    #   # The `From` header of invitation mail can be the mail of the LDAP user
+    #   # Be sure to have a mail system that will correctly send the mail from your users! (DKIM, SPF…)
+    #   # To enable this feature, set it to 1
+    #   # optional, disabled by default
+    #   send_invitation_with_ldap_user_mail => 1,
+    #   # The user is able to set an expiration delay for the invitation.
+    #   # This expiration delay can’t be more than this setting (in days).
+    #   # optional, default is 30 days
+    #   max_invitation_expiration_delay => 30,
+    #   # Once the guest has submitted his files, he has an additional period of time to submit forgotten files.
+    #   # You can set that additional period of time in minutes here.
+    #   # To disable that feature, set it to 0 or less
+    #   # optional, default is 10 minutes
+    #   max_additional_period => 10,
+    #   # Lufi follows privacy-by-design, so, by default, no files URLs (with the decode secret) are stored in database.
+    #   # However, the concern is different for this case. Storing files URLs makes users able to retrieve the guests’ sent files
+    #   # from their `invitations` page.
+    #   # Set to 1 to store guests’ files URLs in database
+    #   # optional, default is 0 (disabled)
+    #   save_files_url_in_db => 0,
+    #   # Users can resend the invitation to their guest. This does not extend the invitation’s expiration delay unless you
+    #   # set this option to 1.
+    #   # optional, default is 0 (disabled)
+    #   extend_invitation_expiration_on_resend => 0,
+    #},
+
+    #########################
+    # Htpasswd authentication
+    #########################
+
+    # Set `htpasswd` if you want to use an htpasswd file instead of ldap
+    # See 'man htpasswd' to know how to create such file
+    #htpasswd => 'lufi.passwd',
+
+    #######################
+    # HTTP Headers settings
+    #######################
+
+    # Content-Security-Policy header that will be sent by Lufi
+    # Set to '' to disable CSP header
+    # https://content-security-policy.com/ provides a good documentation about CSP.
+    # https://report-uri.com/home/generate provides a tool to generate a CSP header.
+    # optional, default is "base-uri 'self'; connect-src 'self' ws://YOUR_HOST; default-src 'none'; font-src 'self'; form-action 'self'; frame-ancestors 'none'; img-src 'self' blob:; media-src blob:; script-src 'self' 'unsafe-inline' 'unsafe-eval'; style-src 'self' 'unsafe-inline'"
+    #csp => "",
+
+    # X-Frame-Options header that will be sent by Lufi
+    # Valid values are: 'DENY', 'SAMEORIGIN', 'ALLOW-FROM https://example.com/'
+    # Set to '' to disable X-Frame-Options header
+    # See https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Frame-Options
+    # Please note that this will add a "frame-ancestors" directive to the CSP header (see above) accordingly
+    # to the chosen setting (See https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/frame-ancestors)
+    # optional, default is 'DENY'
+    #x_frame_options => 'DENY',
+
+    # X-Content-Type-Options that will be sent by Lufi
+    # See https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Content-Type-Options
+    # Set to '' to disable X-Content-Type-Options header
+    # optional, default is 'nosniff'
+    #x_content_type_options => 'nosniff',
+
+    # X-XSS-Protection that will be sent by Lufi
+    # See https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-XSS-Protection
+    # Set to '' to disable X-XSS-Protection header
+    # optional, default is '1; mode=block'
+    #x_xss_protection => '1; mode=block',
+
+    #########################
+    # Lufi cron jobs settings
+    #########################
+
+    # Number of days senders' IP addresses are kept in database
+    # After that delay, they will be deleted from database (used with script/lufi cron cleanbdd)
+    # optional, default is 365
+    keep_ip_during    => 365,
+
+    # Max size of the files directory, in octets
+    # Used by script/lufi cron watch to trigger an action
+    # optional, no default
+    max_total_size    => 10*1024*1024*1024,
+
+    # Default action when files directory is over max_total_size (used with script/lufi cron watch)
+    # Valid values are 'warn', 'stop-upload' and 'delete'
+    # Please, see README.md
+    # optional, default is 'warn'
+    policy_when_full  => 'warn',
+
+    # Files which are not viewed since delete_no_longer_viewed_files days will be deleted by the cron cleanfiles task
+    # If delete_no_longer_viewed_files is not set, the no longer viewed files will NOT be deleted
+    # optional, no default
+    #delete_no_longer_viewed_files => 90,
+};
diff --git a/pica-lufi/lufi.env b/pica-lufi/lufi.env
new file mode 100644
index 0000000000000000000000000000000000000000..6aa2eafc4919d5ac5ddc82b207f86c4f3c1377df
--- /dev/null
+++ b/pica-lufi/lufi.env
@@ -0,0 +1,2 @@
+POSTGRES_PASSWORD=passwd
+POSTGRES_USER=lufidb
diff --git a/pica-lufi/picadrop/Makefile b/pica-lufi/picadrop/Makefile
new file mode 100644
index 0000000000000000000000000000000000000000..48b840f38b11bf73f875e6c8080651d464a508c5
--- /dev/null
+++ b/pica-lufi/picadrop/Makefile
@@ -0,0 +1,27 @@
+EN=lib/Lufi/I18N/en.po
+FR=lib/Lufi/I18N/fr.po
+IT=lib/Lufi/I18N/it.po
+OC=lib/Lufi/I18N/oc.po
+SEDOPTS=-e "s@SOME DESCRIPTIVE TITLE@Lufi language file@" \
+		-e "s@YEAR THE PACKAGE'S COPYRIGHT HOLDER@2015 Luc Didry@" \
+		-e "s@CHARSET@utf8@" \
+		-e "s@the PACKAGE package@the Lufi package@" \
+		-e '/^\#\. (/{N;/\n\#\. (/{N;/\n.*\.\.\/default\//{s/\#\..*\n.*\#\./\#. (/g}}}' \
+		-e '/^\#\. (/{N;/\n.*\.\.\/default\//{s/\n/ /}}'
+SEDOPTS2=-e '/^\#.*\.\.\/default\//,+3d'
+XGETTEXT=carton exec ../../local/bin/xgettext.pl
+CARTON=carton exec
+
+locales:
+		$(XGETTEXT) -D templates -D ../default/templates -o $(EN) 2>/dev/null
+		$(XGETTEXT) -D templates -D ../default/templates -o $(FR) 2>/dev/null
+		$(XGETTEXT) -D templates -D ../default/templates -o $(IT) 2>/dev/null
+		$(XGETTEXT) -D templates -D ../default/templates -o $(OC) 2>/dev/null
+		sed $(SEDOPTS) -i $(EN)
+		sed $(SEDOPTS2) -i $(EN)
+		sed $(SEDOPTS) -i $(FR)
+		sed $(SEDOPTS2) -i $(FR)
+		sed $(SEDOPTS) -i $(IT)
+		sed $(SEDOPTS2) -i $(IT)
+		sed $(SEDOPTS) -i $(OC)
+		sed $(SEDOPTS2) -i $(OC)
diff --git a/pica-lufi/picadrop/lib/Lufi/I18N.pm b/pica-lufi/picadrop/lib/Lufi/I18N.pm
new file mode 100644
index 0000000000000000000000000000000000000000..e6408319b5b882c113ed893a790bcb7cab61ee1e
--- /dev/null
+++ b/pica-lufi/picadrop/lib/Lufi/I18N.pm
@@ -0,0 +1,16 @@
+# vim:set sw=4 ts=4 sts=4 ft=perl expandtab:
+package Lufi::I18N;
+
+use base 'Locale::Maketext';
+use File::Basename qw/dirname/;
+use Locale::Maketext::Lexicon {
+    _auto => 1,
+    _decode => 1,
+    _style  => 'gettext',
+    '*' => [
+        Gettext => dirname(__FILE__) . '/I18N/*.po',
+        Gettext => dirname(__FILE__) . '/../../../default/lib/Lufi/I18N/*.po',
+    ]
+};
+
+1;
diff --git a/pica-lufi/picadrop/public/img/favicon.png b/pica-lufi/picadrop/public/img/favicon.png
new file mode 100644
index 0000000000000000000000000000000000000000..cca7511494ee23c860c7886728009beb9be8fb35
Binary files /dev/null and b/pica-lufi/picadrop/public/img/favicon.png differ
diff --git a/pica-lufi/picadrop/public/img/lufi-min.png b/pica-lufi/picadrop/public/img/lufi-min.png
new file mode 100644
index 0000000000000000000000000000000000000000..396b277624a2ecb8dddade0282dbe18ca2804487
Binary files /dev/null and b/pica-lufi/picadrop/public/img/lufi-min.png differ
diff --git a/pica-lufi/picadrop/public/img/lufi.png b/pica-lufi/picadrop/public/img/lufi.png
new file mode 100644
index 0000000000000000000000000000000000000000..cca7511494ee23c860c7886728009beb9be8fb35
Binary files /dev/null and b/pica-lufi/picadrop/public/img/lufi.png differ
diff --git a/pica-lufi/picadrop/public/img/lufi.xcf b/pica-lufi/picadrop/public/img/lufi.xcf
new file mode 100644
index 0000000000000000000000000000000000000000..4013e3a82b42c44fc7928b6d6bf67c2a07d31edf
Binary files /dev/null and b/pica-lufi/picadrop/public/img/lufi.xcf differ
diff --git a/pica-lufi/picadrop/public/img/lufi120.png b/pica-lufi/picadrop/public/img/lufi120.png
new file mode 100644
index 0000000000000000000000000000000000000000..93e0c2b00422c5c1589ffba41a452b5d27545ad5
Binary files /dev/null and b/pica-lufi/picadrop/public/img/lufi120.png differ
diff --git a/pica-lufi/picadrop/public/img/lufi128.png b/pica-lufi/picadrop/public/img/lufi128.png
new file mode 100644
index 0000000000000000000000000000000000000000..c227b98ee440585b45bd579100db9932456a9652
Binary files /dev/null and b/pica-lufi/picadrop/public/img/lufi128.png differ
diff --git a/pica-lufi/picadrop/public/img/lufi152.png b/pica-lufi/picadrop/public/img/lufi152.png
new file mode 100644
index 0000000000000000000000000000000000000000..5a960e1ce33c869e0864f919952dddc7fa859997
Binary files /dev/null and b/pica-lufi/picadrop/public/img/lufi152.png differ
diff --git a/pica-lufi/picadrop/public/img/lufi196.png b/pica-lufi/picadrop/public/img/lufi196.png
new file mode 100644
index 0000000000000000000000000000000000000000..0e57e092246662d8492f7d614bd72982fb93bdc8
Binary files /dev/null and b/pica-lufi/picadrop/public/img/lufi196.png differ
diff --git a/pica-lufi/picadrop/public/img/lufi60.png b/pica-lufi/picadrop/public/img/lufi60.png
new file mode 100644
index 0000000000000000000000000000000000000000..5d65ffb4a41c128ac65ad081a043700a1388825c
Binary files /dev/null and b/pica-lufi/picadrop/public/img/lufi60.png differ
diff --git a/pica-lufi/picadrop/public/img/lufi76.png b/pica-lufi/picadrop/public/img/lufi76.png
new file mode 100644
index 0000000000000000000000000000000000000000..b2aceecf1fc842f268ce36286c712b40b3f46a2d
Binary files /dev/null and b/pica-lufi/picadrop/public/img/lufi76.png differ
diff --git a/pica-lufi/picadrop/public/img/lufi_favicon.png b/pica-lufi/picadrop/public/img/lufi_favicon.png
new file mode 100644
index 0000000000000000000000000000000000000000..cca7511494ee23c860c7886728009beb9be8fb35
Binary files /dev/null and b/pica-lufi/picadrop/public/img/lufi_favicon.png differ
diff --git a/pica-lufi/picadrop/templates/layouts/default.html.ep b/pica-lufi/picadrop/templates/layouts/default.html.ep
new file mode 100644
index 0000000000000000000000000000000000000000..73a4ba72bbe41ac516fa63dd20d515990edd0060
--- /dev/null
+++ b/pica-lufi/picadrop/templates/layouts/default.html.ep
@@ -0,0 +1,112 @@
+% # vim:set sw=4 ts=4 sts=4 ft=html.epl expandtab:
+% my $lang = $self->languages;
+%    $lang =~ s/-(.*)/_\U$1/;
+<!DOCTYPE html>
+<html>
+    <head>
+        <title><%= config('instance_name') %></title>
+        <meta charset="utf-8">
+        <meta name="mobile-web-app-capable" content="yes">
+        <meta name="apple-mobile-web-app-capable" content="yes">
+        <meta name="apple-mobile-web-app-status-bar-style" content="black">
+        <link rel="icon" type="image/png" href="<%= url_for('/img/favicon.png') %>">
+        <link rel="icon" sizes="128x128" href="<%= url_for('/img/lufi128.png') %>">
+        <link rel="icon" sizes="196x196" href="<%= url_for('/img/lufi196.png') %>">
+        <link rel="apple-touch-icon" href="<%= url_for('/img/lufi60.png') %>">
+        <link rel="apple-touch-icon" sizes="76x76" href="<%= url_for('/img/lufi76.png') %>">
+        <link rel="apple-touch-icon" sizes="120x120" href="<%= url_for('/img/lufi120.png') %>">
+        <link rel="apple-touch-icon" sizes="152x152" href="<%= url_for('/img/lufi152.png') %>">
+        <link rel="apple-touch-icon-precomposed" sizes="128x128" href="<%= url_for('/img/lufi128.png') %>">
+        %= stylesheet '/css/materialize.min.css'
+        %= stylesheet '/css/lufi.css'
+        %= javascript '/js/ie-detection.js'
+        <meta name="viewport" content="width=device-width, initial-scale=1.0">
+    </head>
+    <body>
+        <nav class="cyan">
+            <div class="nav-wrapper container">
+                <a href="<%= url_for('/') %>" class="brand-logo">&nbsp;<img src="<%= url_for('/img/lufi-min.png') %>" alt="logo"> <%= config('instance_name') %></a>
+                <a href="#" data-activates="mobile" class="button-collapse"><i class="mdi-navigation-menu"></i></a>
+                <ul id="nav-mobile" class="right hide-on-med-and-down">
+                    <li><a href="<%= $self->config('report') %>"><%= l('Report file') %></a></li>
+                % if ((!defined(config('ldap')) && !defined(config('htpasswd'))) || is_user_authenticated()) {
+                    <li<%== ' class="active"' if (current_route eq 'index') %>><a href="<%= url_for('/') %>"><%= l('Upload files') %></a></li>
+                    <li<%== ' class="active"' if (current_route eq 'files') %>><a href="<%= url_for('/files') %>"><%= l('My files') %></a></li>
+                    % if (defined config('ldap') && defined config('invitations')) {
+                        <li<%== ' class="active"' if (current_route eq 'invite') %>><a href="<%= url_for('/invite') %>"><%= l('Invite a guest') %></a></li>
+                        <li<%== ' class="active"' if (current_route eq 'invite/list') %>><a href="<%= url_for('/invite/list') %>"><%= l('My invitations') %></a></li>
+                    % }
+                % } else {
+                    <li><a href="<%= url_for('/login') %>"><%= l('Signin') %></a></li>
+                % }
+                    <li>
+                        <div class="input-field select-lang">
+                            <label class="hiddendiv"><%= l('Language') %></label>
+                            <select>
+                                <option value="" disabled selected><%= l('Language') %></option>
+                            % for my $i (@{$self->available_langs}) {
+                                <option value="<%= $i %>"><%= iso639_native_name($i) %></option>
+                            % }
+                            </select>
+                        </div>
+                    </li>
+                    <li<%== ' class="active"' if (current_route eq 'about') %>><a href="<%= url_for('/about') %>"><%= l('About') %></a></li>
+                % if ((defined(config('ldap')) || defined(config('htpasswd'))) && is_user_authenticated()) {
+                    <li>
+                        <form action="<%= url_for('/logout') %>" method="POST">
+                            %= csrf_field
+                            <button class="btn-flat" type="submit"><%= l('Logout') %></button>
+                        </form>
+                    </li>
+                % }
+                    <li><a href="https://picasoft.net/co/cgu.html">CGU</a></li>
+                </ul>
+                <ul id="mobile" class="side-nav">
+                    <li><a href="<%= $self->config('report') %>"><%= l('Report file') %></a></li>
+                % if ((!defined(config('ldap')) && !defined(config('htpasswd'))) || is_user_authenticated()) {
+                    <li<%== ' class="active"' if (current_route eq 'index') %>><a href="<%= url_for('/') %>"><%= l('Upload files') %></a></li>
+                    <li<%== ' class="active"' if (current_route eq 'files') %>><a href="<%= url_for('/files') %>"><%= l('My files') %></a></li>
+                    % if (defined config('ldap') && defined config('invitations')) {
+                        <li<%== ' class="active"' if (current_route eq 'invite') %>><a href="<%= url_for('/invite') %>"><%= l('Invite a guest') %></a></li>
+                        <li<%== ' class="active"' if (current_route eq 'invite/list') %>><a href="<%= url_for('/invite/list') %>"><%= l('My invitations') %></a></li>
+                    % }
+                % } else {
+                    <li><a href="<%= url_for('/login') %>"><%= l('Signin') %></a></li>
+                % }
+                    <li>
+                        <div class="input-field select-lang-mobile">
+                            <label class="hiddendiv"><%= l('Language') %></label>
+                            <select>
+                                <option value="" disabled selected><%= l('Language') %></option>
+                            % for my $i (@{$self->available_langs}) {
+                                <option value="<%= $i %>"><%= iso639_native_name($i) %></option>
+                            % }
+                            </select>
+                        </div>
+                    </li>
+                    <li<%== ' class="active"' if (current_route eq 'about') %>><a href="<%= url_for('/about') %>"><%= l('About') %></a></li>
+                % if ((defined(config('ldap')) || defined(config('htpasswd'))) && is_user_authenticated()) {
+                    <li>
+                        <form action="<%= url_for('/logout') %>" method="POST">
+                            %= csrf_field
+                            <button class="btn-flat" type="submit"><%= l('Logout') %></button>
+                        </form>
+                    </li>
+                % }
+                    <li><a href="https://picasoft.net/co/cgu.html">CGU</a></li>
+                </ul>
+            </div>
+        </nav>
+        <div class="container">
+            %= javascript '/js/jquery-2.2.4.min.js'
+            %= javascript '/partial/layout.js'
+            %= javascript '/js/lufi-common.js'
+            <%= content %>
+        </div>
+% if (defined(config('piwik_img'))) {
+        <img src="<%== config('piwik_img') %>" class="no_border" alt="" />
+% }
+            %= javascript '/js/materialize.js'
+            %= javascript '/js/sidenav.js'
+    </body>
+</html>